1.Gaze Manager
using HoloToolkit;
using UnityEngine;
/// <summary>
/// GazeManager determines the location of the user's gaze, hit position and normals.
/// </summary>
public class GazeManager : Singleton<GazeManager>
{
[Tooltip("Maximum gaze distance for calculating a hit.")]
public float MaxGazeDistance = 5.0f; //The maximum distance within which collides can be detected
[Tooltip("Select the layers raycast should target.")]
public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers;
/// <summary>
/// Physics.Raycast result is true if it hits a Hologram.
/// </summary>
public bool Hit { get; private set; }
/// <summary>
/// HitInfo property gives access
/// to RaycastHit public members.
/// </summary>
public RaycastHit HitInfo { get; private set; }
/// <summary>
/// Position of the user's gaze.
/// </summary>
public Vector3 Position { get; private set; }
/// <summary>
/// RaycastHit Normal direction.
/// </summary>
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();
}
/// <summary>
/// Calculates the Raycast hit position and normal.
/// </summary>
private void UpdateRaycast()
{
RaycastHit hitInfo;
Hit = Physics.Raycast(gazeOrigin,
gazeDirection,
out hitInfo,
MaxGazeDistance,
RaycastLayerMask);
HitInfo = hitInfo;
if (Hit)
{
// If raycast hit a hologram...
Position = hitInfo.point;
Normal = hitInfo.normal;
}
else
{
// If raycast did not hit a hologram...
// Save defaults ...
Position = gazeOrigin + (gazeDirection * MaxGazeDistance);
Normal = gazeDirection;
}
}
}
bool 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()
{
/* TODO: DEVELOPER CODING EXERCISE 2.b */
// 2.b: Instantiate the NavigationRecognizer.
NavigationRecognizer = new GestureRecognizer();
// 2.b: Add Tap and NavigationX GestureSettings to the NavigationRecognizer's RecognizableGestures.
NavigationRecognizer.SetRecognizableGestures(
GestureSettings.Tap |
GestureSettings.NavigationX);
// 2.b: Register for the TappedEvent with the NavigationRecognizer_TappedEvent function.
NavigationRecognizer.TappedEvent += NavigationRecognizer_TappedEvent;
// 2.b: Register for the NavigationStartedEvent with the NavigationRecognizer_NavigationStartedEvent function.
NavigationRecognizer.NavigationStartedEvent += NavigationRecognizer_NavigationStartedEvent;
// 2.b: Register for the NavigationUpdatedEvent with the NavigationRecognizer_NavigationUpdatedEvent function.
NavigationRecognizer.NavigationUpdatedEvent += NavigationRecognizer_NavigationUpdatedEvent;
// 2.b: Register for the NavigationCompletedEvent with the NavigationRecognizer_NavigationCompletedEvent function.
NavigationRecognizer.NavigationCompletedEvent += NavigationRecognizer_NavigationCompletedEvent;
// 2.b: Register for the NavigationCanceledEvent with the NavigationRecognizer_NavigationCanceledEvent function.
NavigationRecognizer.NavigationCanceledEvent += NavigationRecognizer_NavigationCanceledEvent;
// Instantiate the ManipulationRecognizer.
ManipulationRecognizer = new GestureRecognizer();
// Add the ManipulationTranslate GestureSetting to the ManipulationRecognizer's RecognizableGestures.
ManipulationRecognizer.SetRecognizableGestures(
GestureSettings.ManipulationTranslate);
// Register for the Manipulation events on the ManipulationRecognizer.
ManipulationRecognizer.ManipulationStartedEvent += ManipulationRecognizer_ManipulationStartedEvent;
ManipulationRecognizer.ManipulationUpdatedEvent += ManipulationRecognizer_ManipulationUpdatedEvent;
ManipulationRecognizer.ManipulationCompletedEvent += ManipulationRecognizer_ManipulationCompletedEvent;
ManipulationRecognizer.ManipulationCanceledEvent += ManipulationRecognizer_ManipulationCanceledEvent;
ResetGestureRecognizers();
}
将navigation的可识别操作设置为单击以及横向移动(手指移动的横向分量将被检测),
将manipulation则设定为manipulationTranslate(大概是跟随手平移)
注册两种识别器的开始,更新,完成,撤销事件。
void OnDestroy()
{
// 2.b: Unregister the Tapped and Navigation events on the NavigationRecognizer.
NavigationRecognizer.TappedEvent -= NavigationRecognizer_TappedEvent;
NavigationRecognizer.NavigationStartedEvent -= NavigationRecognizer_NavigationStartedEvent;
NavigationRecognizer.NavigationUpdatedEvent -= NavigationRecognizer_NavigationUpdatedEvent;
NavigationRecognizer.NavigationCompletedEvent -= NavigationRecognizer_NavigationCompletedEvent;
NavigationRecognizer.NavigationCanceledEvent -= NavigationRecognizer_NavigationCanceledEvent;
// Unregister the Manipulation events on the ManipulationRecognizer.
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()
{
// Default to the navigation gestures.
Transition(NavigationRecognizer);
}
重置识别器(官方Demo中默认操作是旋转,因此默认的识别器是navigation识别器)private void NavigationRecognizer_NavigationStartedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
{
// 2.b: Set IsNavigating to be true.
IsNavigating = true;
// 2.b: Set NavigationPosition to be relativePosition.
NavigationPosition = relativePosition;
}
private void NavigationRecognizer_NavigationUpdatedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
{
// 2.b: Set IsNavigating to be true.
IsNavigating = true;
// 2.b: Set NavigationPosition to be relativePosition.
NavigationPosition = relativePosition;
}
private void NavigationRecognizer_NavigationCompletedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
{
// 2.b: Set IsNavigating to be false.
IsNavigating = false;
}
private void NavigationRecognizer_NavigationCanceledEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
{
// 2.b: Set IsNavigating to be false.
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()方法。