1.Gaze Manager
using HoloToolkit; using UnityEngine; public class GazeManager : Singleton<GazeManager> { [Tooltip("Maximum gaze distance for calculating a hit." )] public float MaxGazeDistance = 5.0f; [Tooltip("Select the layers raycast should target." )] public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers; public bool Hit { get ; private set ; } public RaycastHit HitInfo { get ; private set ; } public Vector3 Position { get ; private set ; } public Vector3 Normal { get ; private set ; } private GazeStabilizer gazeStabilizer; private Vector3 gazeOrigin; private Vector3 gazeDirection; void Awake() { gazeStabilizer = GetComponent<GazeStabilizer>(); } private void Update() { gazeOrigin = Camera.main.transform.position; gazeDirection = Camera.main.transform.forward; gazeStabilizer.UpdateHeadStability(gazeOrigin, Camera.main.transform.rotation); gazeOrigin = gazeStabilizer.StableHeadPosition; UpdateRaycast(); } private void UpdateRaycast() { RaycastHit hitInfo; Hit = Physics.Raycast(gazeOrigin, gazeDirection, out hitInfo, MaxGazeDistance, RaycastLayerMask); HitInfo = hitInfo; if (Hit) { Position = hitInfo.point; Normal = hitInfo.normal; } else { Position = gazeOrigin + (gazeDirection * MaxGazeDistance); Normal = gazeDirection; } } }
Hit 光标是否与物体发生了碰撞; HitInfo 用来储存碰撞的信息; Position 碰撞点,就是gaze的坐标位置(发生了碰撞时,即Hit == true时),
或是gaze的最远的点(由MaxGazeDistance决定,不发生碰撞时,即Hit == false ) Normal 碰撞点的法线,就是gaze的点的法向量(Hit == true 时),或是gaze的方向(就是gazeDirection,当Hit == false时)。
2.Gesture Manager
public GestureRecognizer NavigationRecognizer { get; private set; } // Manipulation gesture recognizer. public GestureRecognizer ManipulationRecognizer { get; private set; } // Currently active gesture recognizer. public GestureRecognizer ActiveRecognizer { get; private set; } public bool IsNavigating { get; private set; } public Vector3 NavigationPosition { get; private set; } public bool IsManipulating { get; private set; } public Vector3 ManipulationPosition { get; private set; }
两种 识别器的声明:Navigation和Manipulation;分别声明两个bool类型,判断当前识别器是否在运行中;声明Vector3坐标;
void Awake() { NavigationRecognizer = new GestureRecognizer(); NavigationRecognizer.SetRecognizableGestures( GestureSettings.Tap | GestureSettings.NavigationX); NavigationRecognizer.TappedEvent += NavigationRecognizer_TappedEvent; NavigationRecognizer.NavigationStartedEvent += NavigationRecognizer_NavigationStartedEvent; NavigationRecognizer.NavigationUpdatedEvent += NavigationRecognizer_NavigationUpdatedEvent; NavigationRecognizer.NavigationCompletedEvent += NavigationRecognizer_NavigationCompletedEvent; NavigationRecognizer.NavigationCanceledEvent += NavigationRecognizer_NavigationCanceledEvent; ManipulationRecognizer = new GestureRecognizer(); ManipulationRecognizer.SetRecognizableGestures( GestureSettings.ManipulationTranslate); ManipulationRecognizer.ManipulationStartedEvent += ManipulationRecognizer_ManipulationStartedEvent; ManipulationRecognizer.ManipulationUpdatedEvent += ManipulationRecognizer_ManipulationUpdatedEvent; ManipulationRecognizer.ManipulationCompletedEvent += ManipulationRecognizer_ManipulationCompletedEvent; ManipulationRecognizer.ManipulationCanceledEvent += ManipulationRecognizer_ManipulationCanceledEvent; ResetGestureRecognizers(); }
将navigation的可识别操作设置为单击以及横向移动(手指移动的横向分量将被检测),
将manipulation则设定为manipulationTranslate(大概是跟随手平移)
注册两种识别器的开始,更新,完成,撤销事件。
void OnDestroy() { NavigationRecognizer.TappedEvent -= NavigationRecognizer_TappedEvent; NavigationRecognizer.NavigationStartedEvent -= NavigationRecognizer_NavigationStartedEvent; NavigationRecognizer.NavigationUpdatedEvent -= NavigationRecognizer_NavigationUpdatedEvent; NavigationRecognizer.NavigationCompletedEvent -= NavigationRecognizer_NavigationCompletedEvent; NavigationRecognizer.NavigationCanceledEvent -= NavigationRecognizer_NavigationCanceledEvent; ManipulationRecognizer.ManipulationStartedEvent -= ManipulationRecognizer_ManipulationStartedEvent; ManipulationRecognizer.ManipulationUpdatedEvent -= ManipulationRecognizer_ManipulationUpdatedEvent; ManipulationRecognizer.ManipulationCompletedEvent -= ManipulationRecognizer_ManipulationCompletedEvent; ManipulationRecognizer.ManipulationCanceledEvent -= ManipulationRecognizer_ManipulationCanceledEvent; }
注销上述事件
public void Transition(GestureRecognizer newRecognizer) { if (newRecognizer == null ) { return ; } if (ActiveRecognizer != null ) { if (ActiveRecognizer == newRecognizer) { return ; } ActiveRecognizer.CancelGestures(); ActiveRecognizer.StopCapturingGestures(); } newRecognizer.StartCapturingGestures(); ActiveRecognizer = newRecognizer; }
两种识别器之间的变换,比如当前为navigation识别模式,调用Transition(ManipulationRecognizer)可以使manipulation识别器开始工作。
public void ResetGestureRecognizers() { Transition(NavigationRecognizer); }
重置识别器(官方Demo中默认操作是旋转,因此默认的识别器是navigation识别器)
private void NavigationRecognizer_NavigationStartedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray) { IsNavigating = true ; NavigationPosition = relativePosition; } private void NavigationRecognizer_NavigationUpdatedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray) { IsNavigating = true ; NavigationPosition = relativePosition; } private void NavigationRecognizer_NavigationCompletedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray) { IsNavigating = false ; } private void NavigationRecognizer_NavigationCanceledEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray) { IsNavigating = false ; }
各种navigation识别器发生事件之后执行的操作,此处操作是改变IsNavigating的值,即当前识别器的”工作状态“
private void ManipulationRecognizer_ManipulationStartedEvent(InteractionSourceKind source, Vector3 position, Ray ray) { if (HandsManager.Instance.FocusedGameObject != null ) { IsManipulating = true ; ManipulationPosition = position; HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationStart" , position); } } private void ManipulationRecognizer_ManipulationUpdatedEvent(InteractionSourceKind source, Vector3 position, Ray ray) { if (HandsManager.Instance.FocusedGameObject != null ) { IsManipulating = true ; ManipulationPosition = position; HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationUpdate" , position); } } private void ManipulationRecognizer_ManipulationCompletedEvent(InteractionSourceKind source, Vector3 position, Ray ray) { IsManipulating = false ; } private void ManipulationRecognizer_ManipulationCanceledEvent(InteractionSourceKind source, Vector3 position, Ray ray) { IsManipulating = false ; } private void NavigationRecognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray ray) { GameObject focusedObject = InteractibleManager.Instance.FocusedGameObject; if (focusedObject != null ) { focusedObject.SendMessageUpwards("OnSelect" ); } }
manipulation识别事件发生后的操作略有不同,识别开始时让当前焦点物体执行方法 PerformManipulationStart(GestureAction中)初始化物体位置信息,
更新事件发生后让当前焦点物体执行方法PerformManipulationUpdate(GestureAction中)进行物体的平移操作。单击事件将执行Interactible脚本中的OnSelect()方法。