这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/holograms_211

用户操作Hololens的全息对象时需要借助手势,手势的点击类似于我们电脑的鼠标,当我们凝视到某个全息对象时,手势点击即可以得到相应的反馈。这节教程主要讲述如何追踪用户的手势,并对手势操作做出反馈。

这节对手势操作会实现一些新的功能:

1 检测什么时候手势被追踪到然后提供反馈

2 使用导航手势来旋转全息对象。

3 当用户的手移开可检测的范围时提供反馈

4 使用操纵事件来移动全息对象。

前提条件:

  • 一台安装好开发工具的 Windows 10 PC  tools installed.
  • 一些基础的C# 编程能力.
  • 已经完成教程 Holograms 101.
  • 已经完成教程 Holograms 210.
  • 一台 开发者版本的HoloLens 设备

项目文件

勘误表与注释

VS中 "仅我的代码"需要被禁用。在工具-》选项-》调试-》可以找到“仅我的代码”

Unity设置

  • 打开 Unity.
  • 选择Open.
  • 定位到你刚下载的项目文件中的Gesture 文件夹.
  • 选择其中的 Model Explorer 文件夹.
  • 点击 Select Folder 按钮.
  • 在Unity中启动该项目后,在 Project 面板中, 展开 Scenes 文件夹.
  • 双击 ModelExplorer 场景将其加载到Unity中
  • 接下来可以第一次部署发布到你的设备。具体部署发布方法见前两节课程。

章节1 手势检测反馈

目标:
1 注册手势跟踪事件

2 使用光标的变化反馈来显示手是否被跟踪到

步骤:

  • Hierarchy 面板中, 选择 Managers 对象.
  • Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框输入 Hands Manager.选择此结果.

HandsManager.cs 脚本实现如下:

  1. 注册 SourceDetected 和 SourceLost 事件.
  2. 设置手势检测状态 HandDetected state.
  3. 取消注册 SourceDetected 和 SourceLost 事件.
  • Hierarchy 面板, 选择 Cursor 对象.
  • Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框输入Cursor Feedback. 选择此结果.
  • Project 面板下打开 Holograms 文件夹, 找到 HandDetectedFeedback 资源.
  • 拖拽HandDetectedFeedback 资源到Cursor Feedback (Script)组建中的Hand Detected Asset 属性里.
  • Hierarchy 面板里 ,展开 Cursor 对象.
  • 拖拽 CursorBillboard 对象到Cursor Feedback (Script)组建中的Feedback Parent 属性.

CursorFeedback.cs 脚本实现以下行为:

  1. 实例化 HandDetectedFeedback asset.
  2. 指定 HandDetectedFeedback asset 的父对象为 cursor billboard object.
  3. 基于手势检测状态来激活或停用 HandDetectedFeedback asset .

发布部署

  • 当项目部署到hololens 后, 使用 air tap 手势关闭适配盒.
  • 移动你的头部将凝视点对准全息对象,将你的食指竖起在你头部到正前方以便开始追踪手势.
  • 你可以上下左右移动你的手.
  • 查看当你的手被检测到与没有被检测到时光标的变化.

章节2 导航

使用导航手势(食指与大拇指捏合在一起的手势)来旋转全息对象。

步骤:

为了使用导航手势事件,你需要编辑如下四个脚本:

  1. 使用 HandsManager.cs 脚本可以使得目标全息对象被跟踪.
  2. 使用 GestureManager.cs 脚本可以管理导航手势事件.
  3. 当导航手势发生时,旋转操作被管理在 GestureAction.cs脚本中.
  4. 光标通过 CursorStates.cs脚本实现对导航手势操作的样式反馈.
  • VS打开 HandsManager.cs 脚本.更新为如下脚本保存
  1. using HoloToolkit;
  2. using UnityEngine.VR.WSA.Input;
  3. using UnityEngine;
  4.  
  5. /// <summary>
  6. /// HandsManager keeps track of when a hand is detected.
  7. /// </summary>
  8. public class HandsManager : Singleton<HandsManager>
  9. {
  10. [Tooltip("Audio clip to play when Finger Pressed.")]
  11. public AudioClip FingerPressedSound;
  12. private AudioSource audioSource;
  13.  
  14. /// <summary>
  15. /// Tracks the hand detected state.
  16. /// </summary>
  17. public bool HandDetected
  18. {
  19. get;
  20. private set;
  21. }
  22.  
  23. // Keeps track of the GameObject that the hand is interacting with.
  24. public GameObject FocusedGameObject { get; private set; }
  25.  
  26. void Awake()
  27. {
  28. EnableAudioHapticFeedback();
  29.  
  30. InteractionManager.SourceDetected += InteractionManager_SourceDetected;
  31. InteractionManager.SourceLost += InteractionManager_SourceLost;
  32.  
  33. /* TODO: DEVELOPER CODE ALONG 2.a */
  34.  
  35. // 2.a: Register for SourceManager.SourcePressed event.
  36. InteractionManager.SourcePressed += InteractionManager_SourcePressed;
  37.  
  38. // 2.a: Register for SourceManager.SourceReleased event.
  39. InteractionManager.SourceReleased += InteractionManager_SourceReleased;
  40.  
  41. // 2.a: Initialize FocusedGameObject as null.
  42. FocusedGameObject = null;
  43. }
  44.  
  45. private void EnableAudioHapticFeedback()
  46. {
  47. // If this hologram has an audio clip, add an AudioSource with this clip.
  48. if (FingerPressedSound != null)
  49. {
  50. audioSource = GetComponent<AudioSource>();
  51. if (audioSource == null)
  52. {
  53. audioSource = gameObject.AddComponent<AudioSource>();
  54. }
  55.  
  56. audioSource.clip = FingerPressedSound;
  57. audioSource.playOnAwake = false;
  58. audioSource.spatialBlend = ;
  59. audioSource.dopplerLevel = ;
  60. }
  61. }
  62.  
  63. private void InteractionManager_SourceDetected(InteractionSourceState hand)
  64. {
  65. HandDetected = true;
  66. }
  67.  
  68. private void InteractionManager_SourceLost(InteractionSourceState hand)
  69. {
  70. HandDetected = false;
  71.  
  72. // 2.a: Reset FocusedGameObject.
  73. ResetFocusedGameObject();
  74. }
  75.  
  76. private void InteractionManager_SourcePressed(InteractionSourceState hand)
  77. {
  78. if (InteractibleManager.Instance.FocusedGameObject != null)
  79. {
  80. // Play a select sound if we have an audio source and are not targeting an asset with a select sound.
  81. if (audioSource != null && !audioSource.isPlaying &&
  82. (InteractibleManager.Instance.FocusedGameObject.GetComponent<Interactible>() != null &&
  83. InteractibleManager.Instance.FocusedGameObject.GetComponent<Interactible>().TargetFeedbackSound == null))
  84. {
  85. audioSource.Play();
  86. }
  87.  
  88. // 2.a: Cache InteractibleManager's FocusedGameObject in FocusedGameObject.
  89. FocusedGameObject = InteractibleManager.Instance.FocusedGameObject;
  90. }
  91. }
  92.  
  93. private void InteractionManager_SourceReleased(InteractionSourceState hand)
  94. {
  95. // 2.a: Reset FocusedGameObject.
  96. ResetFocusedGameObject();
  97. }
  98.  
  99. private void ResetFocusedGameObject()
  100. {
  101. // 2.a: Set FocusedGameObject to be null.
  102. FocusedGameObject = null;
  103.  
  104. // 2.a: On GestureManager call ResetGestureRecognizers
  105. // to complete any currently active gestures.
  106. GestureManager.Instance.ResetGestureRecognizers();
  107. }
  108.  
  109. void OnDestroy()
  110. {
  111. InteractionManager.SourceDetected -= InteractionManager_SourceDetected;
  112. InteractionManager.SourceLost -= InteractionManager_SourceLost;
  113.  
  114. // 2.a: Unregister the SourceManager.SourceReleased event.
  115. InteractionManager.SourceReleased -= InteractionManager_SourceReleased;
  116.  
  117. // 2.a: Unregister for SourceManager.SourcePressed event.
  118. InteractionManager.SourcePressed -= InteractionManager_SourcePressed;
  119. }
  120. }

HandsManager

  • Hierarchy 面板中, 点击 Cursor.
  • 在Project面板下 HoloToolkit\Input\Prefabs 文件夹, 找到 ScrollFeedback asset.
  • 拖拽 ScrollFeedback asset 到 右侧Inspector面板下的Cursor Feedback (Script)组件里的Scroll Detected Asset 属性。
  • Hierarchy 面板中, 点击AstroMan 对象.
  • Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框内输入 Gesture Action. 选择此结果.
  • Hierarchy 面板下, 选择 Managers 对象.
  • 用VS打开GestureManager 脚本。

我们需要编辑GestureManager.cs 脚本来完成如下几步:

  1. 将NavigationRecognizer实例化为新的GestureRecognizer.
  2. 使用 SetRecognizableGestures 来识别 NavigationXTap 手势.
  3. 处理 NavigationStarted, NavigationUpdated, NavigationCompleted, NavigationCanceled 事件.
  1. using HoloToolkit;
  2. using UnityEngine;
  3. using UnityEngine.VR.WSA.Input;
  4.  
  5. public class GestureManager : Singleton<GestureManager>
  6. {
  7. // Tap and Navigation gesture recognizer.
  8. public GestureRecognizer NavigationRecognizer { get; private set; }
  9.  
  10. // Manipulation gesture recognizer.
  11. public GestureRecognizer ManipulationRecognizer { get; private set; }
  12.  
  13. // Currently active gesture recognizer.
  14. public GestureRecognizer ActiveRecognizer { get; private set; }
  15.  
  16. public bool IsNavigating { get; private set; }
  17.  
  18. public Vector3 NavigationPosition { get; private set; }
  19.  
  20. public bool IsManipulating { get; private set; }
  21.  
  22. public Vector3 ManipulationPosition { get; private set; }
  23.  
  24. void Awake()
  25. {
  26. /* TODO: DEVELOPER CODING EXERCISE 2.b */
  27.  
  28. // 2.b: Instantiate the NavigationRecognizer.
  29. NavigationRecognizer = new GestureRecognizer();
  30.  
  31. // 2.b: Add Tap and NavigationX GestureSettings to the NavigationRecognizer's RecognizableGestures.
  32. NavigationRecognizer.SetRecognizableGestures(
  33. GestureSettings.Tap |
  34. GestureSettings.NavigationX);
  35.  
  36. // 2.b: Register for the TappedEvent with the NavigationRecognizer_TappedEvent function.
  37. NavigationRecognizer.TappedEvent += NavigationRecognizer_TappedEvent;
  38. // 2.b: Register for the NavigationStartedEvent with the NavigationRecognizer_NavigationStartedEvent function.
  39. NavigationRecognizer.NavigationStartedEvent += NavigationRecognizer_NavigationStartedEvent;
  40. // 2.b: Register for the NavigationUpdatedEvent with the NavigationRecognizer_NavigationUpdatedEvent function.
  41. NavigationRecognizer.NavigationUpdatedEvent += NavigationRecognizer_NavigationUpdatedEvent;
  42. // 2.b: Register for the NavigationCompletedEvent with the NavigationRecognizer_NavigationCompletedEvent function.
  43. NavigationRecognizer.NavigationCompletedEvent += NavigationRecognizer_NavigationCompletedEvent;
  44. // 2.b: Register for the NavigationCanceledEvent with the NavigationRecognizer_NavigationCanceledEvent function.
  45. NavigationRecognizer.NavigationCanceledEvent += NavigationRecognizer_NavigationCanceledEvent;
  46.  
  47. // Instantiate the ManipulationRecognizer.
  48. ManipulationRecognizer = new GestureRecognizer();
  49.  
  50. // Add the ManipulationTranslate GestureSetting to the ManipulationRecognizer's RecognizableGestures.
  51. ManipulationRecognizer.SetRecognizableGestures(
  52. GestureSettings.ManipulationTranslate);
  53.  
  54. // Register for the Manipulation events on the ManipulationRecognizer.
  55. ManipulationRecognizer.ManipulationStartedEvent += ManipulationRecognizer_ManipulationStartedEvent;
  56. ManipulationRecognizer.ManipulationUpdatedEvent += ManipulationRecognizer_ManipulationUpdatedEvent;
  57. ManipulationRecognizer.ManipulationCompletedEvent += ManipulationRecognizer_ManipulationCompletedEvent;
  58. ManipulationRecognizer.ManipulationCanceledEvent += ManipulationRecognizer_ManipulationCanceledEvent;
  59.  
  60. ResetGestureRecognizers();
  61. }
  62.  
  63. void OnDestroy()
  64. {
  65. // 2.b: Unregister the Tapped and Navigation events on the NavigationRecognizer.
  66. NavigationRecognizer.TappedEvent -= NavigationRecognizer_TappedEvent;
  67.  
  68. NavigationRecognizer.NavigationStartedEvent -= NavigationRecognizer_NavigationStartedEvent;
  69. NavigationRecognizer.NavigationUpdatedEvent -= NavigationRecognizer_NavigationUpdatedEvent;
  70. NavigationRecognizer.NavigationCompletedEvent -= NavigationRecognizer_NavigationCompletedEvent;
  71. NavigationRecognizer.NavigationCanceledEvent -= NavigationRecognizer_NavigationCanceledEvent;
  72.  
  73. // Unregister the Manipulation events on the ManipulationRecognizer.
  74. ManipulationRecognizer.ManipulationStartedEvent -= ManipulationRecognizer_ManipulationStartedEvent;
  75. ManipulationRecognizer.ManipulationUpdatedEvent -= ManipulationRecognizer_ManipulationUpdatedEvent;
  76. ManipulationRecognizer.ManipulationCompletedEvent -= ManipulationRecognizer_ManipulationCompletedEvent;
  77. ManipulationRecognizer.ManipulationCanceledEvent -= ManipulationRecognizer_ManipulationCanceledEvent;
  78. }
  79.  
  80. /// <summary>
  81. /// Revert back to the default GestureRecognizer.
  82. /// </summary>
  83. public void ResetGestureRecognizers()
  84. {
  85. // Default to the navigation gestures.
  86. Transition(NavigationRecognizer);
  87. }
  88.  
  89. /// <summary>
  90. /// Transition to a new GestureRecognizer.
  91. /// </summary>
  92. /// <param name="newRecognizer">The GestureRecognizer to transition to.</param>
  93. public void Transition(GestureRecognizer newRecognizer)
  94. {
  95. if (newRecognizer == null)
  96. {
  97. return;
  98. }
  99.  
  100. if (ActiveRecognizer != null)
  101. {
  102. if (ActiveRecognizer == newRecognizer)
  103. {
  104. return;
  105. }
  106.  
  107. ActiveRecognizer.CancelGestures();
  108. ActiveRecognizer.StopCapturingGestures();
  109. }
  110.  
  111. newRecognizer.StartCapturingGestures();
  112. ActiveRecognizer = newRecognizer;
  113. }
  114.  
  115. private void NavigationRecognizer_NavigationStartedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
  116. {
  117. // 2.b: Set IsNavigating to be true.
  118. IsNavigating = true;
  119.  
  120. // 2.b: Set NavigationPosition to be relativePosition.
  121. NavigationPosition = relativePosition;
  122. }
  123.  
  124. private void NavigationRecognizer_NavigationUpdatedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
  125. {
  126. // 2.b: Set IsNavigating to be true.
  127. IsNavigating = true;
  128.  
  129. // 2.b: Set NavigationPosition to be relativePosition.
  130. NavigationPosition = relativePosition;
  131. }
  132.  
  133. private void NavigationRecognizer_NavigationCompletedEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
  134. {
  135. // 2.b: Set IsNavigating to be false.
  136. IsNavigating = false;
  137. }
  138.  
  139. private void NavigationRecognizer_NavigationCanceledEvent(InteractionSourceKind source, Vector3 relativePosition, Ray ray)
  140. {
  141. // 2.b: Set IsNavigating to be false.
  142. IsNavigating = false;
  143. }
  144.  
  145. private void ManipulationRecognizer_ManipulationStartedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
  146. {
  147. if (HandsManager.Instance.FocusedGameObject != null)
  148. {
  149. IsManipulating = true;
  150.  
  151. ManipulationPosition = position;
  152.  
  153. HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationStart", position);
  154. }
  155. }
  156.  
  157. private void ManipulationRecognizer_ManipulationUpdatedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
  158. {
  159. if (HandsManager.Instance.FocusedGameObject != null)
  160. {
  161. IsManipulating = true;
  162.  
  163. ManipulationPosition = position;
  164.  
  165. HandsManager.Instance.FocusedGameObject.SendMessageUpwards("PerformManipulationUpdate", position);
  166. }
  167. }
  168.  
  169. private void ManipulationRecognizer_ManipulationCompletedEvent(InteractionSourceKind source, Vector3 position, Ray ray)
  170. {
  171. IsManipulating = false;
  172. }
  173.  
  174. private void ManipulationRecognizer_ManipulationCanceledEvent(InteractionSourceKind source, Vector3 position, Ray ray)
  175. {
  176. IsManipulating = false;
  177. }
  178.  
  179. private void NavigationRecognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray ray)
  180. {
  181. GameObject focusedObject = InteractibleManager.Instance.FocusedGameObject;
  182.  
  183. if (focusedObject != null)
  184. {
  185. focusedObject.SendMessageUpwards("OnSelect");
  186. }
  187. }
  188. }

GestureManager

接下来,需要用VS打开并编辑GestureAction.cs脚本,需要实现如下几点:

  1. 每当执行导航手势时,旋转AstroMan对象.
  2. 计算 rotationFactor以控制应用于对象的旋转量.
  3. 当用户向左或向右移动手时,围绕y轴旋转对象.
  1. using UnityEngine;
  2.  
  3. /// <summary>
  4. /// GestureAction performs custom actions based on
  5. /// which gesture is being performed.
  6. /// </summary>
  7. public class GestureAction : MonoBehaviour
  8. {
  9. [Tooltip("Rotation max speed controls amount of rotation.")]
  10. public float RotationSensitivity = 10.0f;
  11.  
  12. private Vector3 manipulationPreviousPosition;
  13.  
  14. private float rotationFactor;
  15.  
  16. void Update()
  17. {
  18. PerformRotation();
  19. }
  20.  
  21. private void PerformRotation()
  22. {
  23. if (GestureManager.Instance.IsNavigating &&
  24. (!ExpandModel.Instance.IsModelExpanded ||
  25. (ExpandModel.Instance.IsModelExpanded && HandsManager.Instance.FocusedGameObject == gameObject)))
  26. {
  27. /* TODO: DEVELOPER CODING EXERCISE 2.c */
  28.  
  29. // 2.c: Calculate rotationFactor based on GestureManager's NavigationPosition.X and multiply by RotationSensitivity.
  30. // This will help control the amount of rotation.
  31. rotationFactor = GestureManager.Instance.NavigationPosition.x * RotationSensitivity;
  32.  
  33. // 2.c: transform.Rotate along the Y axis using rotationFactor.
  34. transform.Rotate(new Vector3(, - * rotationFactor, ));
  35. }
  36. }
  37.  
  38. void PerformManipulationStart(Vector3 position)
  39. {
  40. manipulationPreviousPosition = position;
  41. }
  42.  
  43. void PerformManipulationUpdate(Vector3 position)
  44. {
  45. if (GestureManager.Instance.IsManipulating)
  46. {
  47. /* TODO: DEVELOPER CODING EXERCISE 4.a */
  48.  
  49. Vector3 moveVector = Vector3.zero;
  50.  
  51. // 4.a: Calculate the moveVector as position - manipulationPreviousPosition.
  52.  
  53. // 4.a: Update the manipulationPreviousPosition with the current position.
  54.  
  55. // 4.a: Increment this transform's position by the moveVector.
  56. }
  57. }
  58. }

GestureAction

发布部署:
    1  凝视宇航员,两个箭头应该会出现在光标的两侧。 这个新的光标表示宇航员可以被旋转。
    2  将你的手放在可以识别的位置(食指指向天空),然后HoloLens将开始跟踪你的手。
    3  要旋转宇航员,将食指放低与大拇指合并,然后向左或向右移动手可以触发NavigationX手势。

章节 3 手势引导

使用 hand guidance score 来帮助预测 被检测的手势何时会丢失.当用户的手进入摄像机视角范围内时提供光标反馈。

步骤:

  • Hierarchy 面板中, 选择 Managers 对象.
  • 在右侧的 Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框内输入 Hand Guidance. 选择此结果.
  • Project 面板下的HoloToolkit\Input\Prefabs 文件夹,找到 HandGuidanceFeedback asset.
  • 拖拽 HandGuidanceFeedback asset 到右侧Inspector 面板下到Hand Guidance Indicator 属性.
  • Hierarchy 面板, 展开 Cursor 对象.
  • Hierarchy 面板, 选择 Managers 对象.
  • 拖拽Cursor对象下的 CursorBillboard 到右侧Inspector面板的Indicator Parent 属性中。

部署发布:

可以看到当你的手势进入到摄像机视角时,会出现一个小手图标表明你的手势被追踪到。

章节 4 Manipulation(操作控制)

使用操作事件来移动你的全息图,给光标一个样式反馈到用户表明什么时候操作行为被激活。

步骤:

GestureManager.cs 和 AstronautManager.cs 脚本可以实现如下功能:

  1. 使用语音关键字 "Move Astronaut" 来激活 Manipulation 手势.
  2. 选择使用 Manipulation Gesture Recognizer.
  3. 在导航和操作之间切换时管理GestureRecognizer过渡.

开始实现

  • Hierarchy 面板中, 选择 Managers 对象.
  • 在右侧的 Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框输入 Astronaut Manager. 选择此结果.
  • Hierarchy 面板, 点击 Cursor.
  • Project 面板下到 Holotoolkit\Input\Prefabs 文件夹中找到 PathingFeedback asset.
  • 拖拽PathingFeedback asset 到Inspector面板下的Cursor States (Script)组件中的Pathing Detected Asset 属性.

接下来需要再次编辑GestureAction.cs脚本文件

  1. using UnityEngine;
  2.  
  3. /// <summary>
  4. /// GestureAction performs custom actions based on
  5. /// which gesture is being performed.
  6. /// </summary>
  7. public class GestureAction : MonoBehaviour
  8. {
  9. [Tooltip("Rotation max speed controls amount of rotation.")]
  10. public float RotationSensitivity = 10.0f;
  11.  
  12. private Vector3 manipulationPreviousPosition;
  13.  
  14. private float rotationFactor;
  15.  
  16. void Update()
  17. {
  18. PerformRotation();
  19. }
  20.  
  21. private void PerformRotation()
  22. {
  23. if (GestureManager.Instance.IsNavigating &&
  24. (!ExpandModel.Instance.IsModelExpanded ||
  25. (ExpandModel.Instance.IsModelExpanded && HandsManager.Instance.FocusedGameObject == gameObject)))
  26. {
  27. /* TODO: DEVELOPER CODING EXERCISE 2.c */
  28.  
  29. // 2.c: Calculate rotationFactor based on GestureManager's NavigationPosition.X and multiply by RotationSensitivity.
  30. // This will help control the amount of rotation.
  31. rotationFactor = GestureManager.Instance.NavigationPosition.x * RotationSensitivity;
  32.  
  33. // 2.c: transform.Rotate along the Y axis using rotationFactor.
  34. transform.Rotate(new Vector3(, - * rotationFactor, ));
  35. }
  36. }
  37.  
  38. void PerformManipulationStart(Vector3 position)
  39. {
  40. manipulationPreviousPosition = position;
  41. }
  42.  
  43. void PerformManipulationUpdate(Vector3 position)
  44. {
  45. if (GestureManager.Instance.IsManipulating)
  46. {
  47. /* TODO: DEVELOPER CODING EXERCISE 4.a */
  48.  
  49. Vector3 moveVector = Vector3.zero;
  50.  
  51. // 4.a: Calculate the moveVector as position - manipulationPreviousPosition.
  52. moveVector = position - manipulationPreviousPosition;
  53.  
  54. // 4.a: Update the manipulationPreviousPosition with the current position.
  55. manipulationPreviousPosition = position;
  56.  
  57. // 4.a: Increment this transform's position by the moveVector.
  58. transform.position += moveVector;
  59. }
  60. }
  61. }

GestureAction

部署发布:

1.发布完成后,在你的设备前移动你的手,伸出你的食指指向天空以便手势被追踪到

2 将凝视光标指向太空宇航员

3 说“Move Astronaut”来用操作手势移动宇航员

4光标周围应出现四个箭头,表示程序现在将响应操作事件。

5把你的食指放在你的拇指上,并保持他们捏在一起。

6当你移动你的手,宇航员也会移动(这是操作)。

7抬起你的食指,停止操作移动宇航员。
8注意:如果您在移动手之前不说“Move Astronaut”,则会改用导航手势。

章节5 模型扩展

使用爆炸动画效果将宇航员拆分为很多小的碎片,每一个小碎片都可以进行移动和旋转操作。

爆炸操作使用语音指令“Expand Model

恢复原模型使用语音指令“Reset Model

编辑AstronautManager.cs 代码

  1. using HoloToolkit;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.Windows.Speech;
  6.  
  7. public class AstronautManager : Singleton<AstronautManager>
  8. {
  9. float expandAnimationCompletionTime;
  10. // Store a bool for whether our astronaut model is expanded or not.
  11. bool isModelExpanding = false;
  12.  
  13. // KeywordRecognizer object.
  14. KeywordRecognizer keywordRecognizer;
  15.  
  16. // Defines which function to call when a keyword is recognized.
  17. delegate void KeywordAction(PhraseRecognizedEventArgs args);
  18. Dictionary<string, KeywordAction> keywordCollection;
  19.  
  20. void Start()
  21. {
  22. keywordCollection = new Dictionary<string, KeywordAction>();
  23.  
  24. // Add keyword to start manipulation.
  25. keywordCollection.Add("Move Astronaut", MoveAstronautCommand);
  26.  
  27. // Add keyword Expand Model to call the ExpandModelCommand function.
  28. keywordCollection.Add("Expand Model", ExpandModelCommand);
  29.  
  30. // Add keyword Reset Model to call the ResetModelCommand function.
  31. keywordCollection.Add("Reset Model", ResetModelCommand);
  32.  
  33. // Initialize KeywordRecognizer with the previously added keywords.
  34. keywordRecognizer = new KeywordRecognizer(keywordCollection.Keys.ToArray());
  35. keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
  36. keywordRecognizer.Start();
  37. }
  38.  
  39. private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
  40. {
  41. KeywordAction keywordAction;
  42.  
  43. if (keywordCollection.TryGetValue(args.text, out keywordAction))
  44. {
  45. keywordAction.Invoke(args);
  46. }
  47. }
  48.  
  49. private void MoveAstronautCommand(PhraseRecognizedEventArgs args)
  50. {
  51. GestureManager.Instance.Transition(GestureManager.Instance.ManipulationRecognizer);
  52. }
  53.  
  54. private void ResetModelCommand(PhraseRecognizedEventArgs args)
  55. {
  56. // Reset local variables.
  57. isModelExpanding = false;
  58.  
  59. // Disable the expanded model.
  60. ExpandModel.Instance.ExpandedModel.SetActive(false);
  61.  
  62. // Enable the idle model.
  63. ExpandModel.Instance.gameObject.SetActive(true);
  64.  
  65. // Enable the animators for the next time the model is expanded.
  66. Animator[] expandedAnimators = ExpandModel.Instance.ExpandedModel.GetComponentsInChildren<Animator>();
  67. foreach (Animator animator in expandedAnimators)
  68. {
  69. animator.enabled = true;
  70. }
  71.  
  72. ExpandModel.Instance.Reset();
  73. }
  74.  
  75. private void ExpandModelCommand(PhraseRecognizedEventArgs args)
  76. {
  77. // Swap out the current model for the expanded model.
  78. GameObject currentModel = ExpandModel.Instance.gameObject;
  79.  
  80. ExpandModel.Instance.ExpandedModel.transform.position = currentModel.transform.position;
  81. ExpandModel.Instance.ExpandedModel.transform.rotation = currentModel.transform.rotation;
  82. ExpandModel.Instance.ExpandedModel.transform.localScale = currentModel.transform.localScale;
  83.  
  84. currentModel.SetActive(false);
  85. ExpandModel.Instance.ExpandedModel.SetActive(true);
  86.  
  87. // Play animation. Ensure the Loop Time check box is disabled in the inspector for this animation to play it once.
  88. Animator[] expandedAnimators = ExpandModel.Instance.ExpandedModel.GetComponentsInChildren<Animator>();
  89. // Set local variables for disabling the animation.
  90. if (expandedAnimators.Length > )
  91. {
  92. expandAnimationCompletionTime = Time.realtimeSinceStartup + expandedAnimators[].runtimeAnimatorController.animationClips[].length * 0.9f;
  93. }
  94.  
  95. // Set the expand model flag.
  96. isModelExpanding = true;
  97.  
  98. ExpandModel.Instance.Expand();
  99. }
  100.  
  101. public void Update()
  102. {
  103. if (isModelExpanding && Time.realtimeSinceStartup >= expandAnimationCompletionTime)
  104. {
  105. isModelExpanding = false;
  106.  
  107. Animator[] expandedAnimators = ExpandModel.Instance.ExpandedModel.GetComponentsInChildren<Animator>();
  108.  
  109. foreach (Animator animator in expandedAnimators)
  110. {
  111. animator.enabled = false;
  112. }
  113. }
  114. }
  115. }

AstronautManager

发布部署到设备:

  • Expand Model 来观看爆炸效果.
  • 使用 Navigation 操作来旋转每一个碎片.
  • Move Astronaut 出现移动光标时,使用 Manipulation 操作移动每一个小碎片.
  • Reset Model 将模型恢复到初始状态.

原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/holograms_211

如有翻译上的错误请指正。谢谢哦

微软Hololens学院教程-Hologram 211-Gestures(手势)【微软教程已经更新,本文是老版本】的更多相关文章

  1. 微软Hololens学院教程-Hologram 230-空间场景建模(Spatial mapping )【微软教程已经更新,本文是老版本】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  2. 微软Hololens学院教程-Hologram 212-Voice(语音)【微软教程已经更新,本文是老版本】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  3. 微软Hololens学院教程-Hologram 210 Gaze(凝视)【微软教程已经更新,本文是老版本】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  4. 微软Hololens学院教程-Hologram 220-空间声音(Spatial sound )【本文是老版本,与最新的微软教程有出入】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦! 原文链接https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  5. 微软Hololens学院教程- Holograms 101: Introduction with Device【微软教程已经更新,本文是老版本】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  6. 微软Hololens学院教程- Holograms 100: Getting Started with Unity【微软教程已经更新,本文是老版本】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦!原文链接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  7. Android基础新手教程——3.8 Gestures(手势)

    Android基础新手教程--3.8 Gesture(手势) 标签(空格分隔): Android基础新手教程 本节引言: 周六不歇息,刚剪完了个大平头回来.继续码字~ 好的,本节给大家带来点的是第三章 ...

  8. 微软Hololens设备 浅分析

    微软Hololens的定位是一款MR 设备(Mixed reality).MR与AR的不同我认为是MR能够将真实环境的场景信息与虚拟对象进行完美的融合,它是基于SLAM(SimultaneousLoc ...

  9. 微软HoloLens技术解谜

    HoloLens 是什么? HoloLens 是微软发布的可穿戴式增强现实计算设备,它拥有这么几个关键要素: 它是增强现实产品,即 Augmented Reality(AR),AR 技术将计算机生成的 ...

随机推荐

  1. Flex学习第一天(两个数相加)

    <?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="htt ...

  2. Oracle inactive session (last_call_et)

    注意last_call_et的值, select s.status,s.last_call_et,s.* from v$session s where username='DDD'; 在本例中,开了个 ...

  3. 【技巧】centos6.5_yum本地安装mysql

    环境:centos6.5 .64位.mysql5.6.3 有鉴于此前在网上得来的Yum换源安装mysql,成功是可以成功,就是会受网速等影响,有时候会因为yum下载rpm包很慢以致超时失败. 而且考虑 ...

  4. 在Linux平台上用ASP.NET 5 连接Redis服务器

    最近在做一个Linux平台上基于ASP.Net 5 中间件+Redis+Mysql架构的系统,研究使用了 StackExchange.Redis 作为asp.net5连接redis的工具.作者在前几天 ...

  5. 关于SWT中的布局Layout

    组件装在容器里,那么这些组件是如何布局的呢?在这之前所有的例子都是使用setBounds来 进行绝对坐标的定位的. 在实际应用过程中大都是采用布局管理器的方式来布局容器中的组件. 布局管理器定义了组件 ...

  6. jQuery图片无缝滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. jemter接口测试之---接口测试的一些约定

      一.接口规范 1.前端请求接口 请求数据格式:appType =1&args ={json}&session =xxx&timestamp =now&sign =x ...

  8. xilinx 网站资源导读

    [经验整理.01]Xilinx网站资源导读 ISE11版 标签:  ISE  Xilinx  入门  资源  2009-09-01 20:41 序 虽然自己也曾想过,但如果不是向农要求,把曾经写过的文 ...

  9. 读jQuery官方文档:$(document).ready()与避免冲突

    $(document).ready() 通常你想在DOM结构加载完毕之后才执行相关脚本.使用原生JavaScript,你可能调用window.onload = function() { ... }, ...

  10. 使用 x3dom 框架及 WebGL 在浏览器上显示 3 维模型

    如果需要在浏览器上显示 3D 画面的话, 现在一般会使用 ​WebGL, 典型的例如 three.js(​http://mrdoob.github.com/three.js/), 但是 WebGL 对 ...