手部菜单 — MRTK2

手部菜单 UX 示例

通过手动菜单,用户可以快速调出常用功能的手动连接 UI。 为了防止与其他对象交互时出现误激活,手部菜单提供了“需要平手”和“使用凝视激活”等选项。 建议使用这些选项来防止不需要的激活。

手动菜单示例

HandMenuExamples.unity 场景位于 MRTK/Examples/Demos/HandTracking/Scenes 文件夹下。 运行时,场景将仅激活当前选定的菜单类型。
HandMenu_ExampleScene

可以在 MRTK/Examples/Common/Prefabs 文件夹下找到这些手动菜单预制件。

HandMenu_Small_HideOnHandDrop 和 HandMenu_Medium_HideOnHandDrop

这两个示例只是激活和停用 MenuContent 对象,以在发生 OnFirstHandDetected() 和 OnLastHandLost() 事件时显示和隐藏菜单。
HandMenu_ExampleScene 1
HandMenu_ExampleScene 2

HandMenu_Large_WorldLock_On_GrabAndPull

对于需要较长交互时间的更复杂的菜单,建议对菜单进行世界锁定。 在此示例中,除了在发生 OnFirstHandDetected() 和 OnLastHandLost() 事件时激活和停用 MenuContent 之外,用户还可以抓取并拉动菜单以进行世界锁定。
HandMenu_ExampleScene 3

背板的 ManipulationHandler 使其变得可抓取并且可移动。 “在操作已启动时”事件,停用 SolverHandler.UpdateSolvers 以在世界锁定菜单。 此外,它还显示关闭按钮,用户可以使用该按钮在任务完成时关闭菜单。 “在操作结束时”事件,该事件调用 HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine,这样用户通过抬手并注视手掌便可在手掌中显示菜单。
HandMenu_ExampleScene 4

关闭 按钮会重新激活 SolverHandler.UpdateSolvers 并隐藏 MenuContent
HandMenu_ExampleScene 5

HandMenu_Large_AutoWorldLock_On_HandDrop

此示例类似于 HandMenu_Large_WorldLock_On_GrabAndPull。 唯一的区别是菜单会在手放下时自动世界锁定。 此行为是通过不隐藏 OnLastHandLost () 上的 MenuContent 事件来处理的。 抓取并拉动的行为与 HandMenu_Large_WorldLock_On_GrabAndPull 示例相同。

脚本

HandConstraint 行为提供了一个求解器,该求解器将跟踪的对象限制在手部受约束内容 ((如手部 UI、菜单等)) 的安全区域。 安全区域是指不会与手部相交的区域。 还包含了一个名为 HandConstraintPalmUpHandConstraint 派生类,用于演示手掌朝向用户时激活求解器的常见行为。

有关更多文档,请参阅每个 HandConstraint 属性可用的工具提示。 下面更详细地定义了一些属性。

HandMenu_ExampleScene掌向上
  • 安全区域:安全区域指定了手掌上限制内容的区域。 建议将内容放置在 Ulnar 侧,以避免与手部重叠并改进交互质量。 安全区域的计算方法是将手部方向投影到与相机视野正交的平面中,并针对手部周围的边界框进行光线投射。 安全区域规定为与 IMixedRealityHand 一起使用,但也可与其他控制器类型一起使用。 建议了解每个安全区域在不同控制器类型上表示的内容。

  • 跟随手直到对着相机 启用此设置后,求解器将跟随手部旋转,直到菜单与凝视充分对齐,此时它面向相机。 此行为的工作原理是将 HandConstraintSolver 中的 SolverRotationBehavior 从 LookAtTrackedObject 更改为 LookAtMainCamera,因为求解器的 GazeAlignment 角度会有所不同。

HandMenu 安全区域
  • 激活事件:目前 HandConstraint 触发四个激活事件。 可以在许多不同的组合中使用这些事件来创建独特的 HandConstraint 行为。有关这些行为的示例,请参阅下面的 MRTK/Examples/Demos/HandTracking/Scenes/ HandBasedMenuExample 场景。

    • OnHandActivate:当手形满足 IsHandActive 方法时触发。
    • OnHandDeactivate:当不再满足 IsHandActive 时触发。
    • OnFirstHandDetected:当手部跟踪状态从视野中没有手形变为视野中出现第一个手形时触发。
    • OnLastHandLost:当手部跟踪状态从视野中至少出现一个手形变为视野中没有手形时触发。
  • 规划求解激活/停用逻辑:目前激活和停用 HandConstraintPalmUp 逻辑的建议是使用 SolverHandler 的 UpdateSolver 值,而不是禁用/启用对象。 可以通过附加菜单的 ManipulationHandler“OnManipulationStarted/结束”事件后触发的基于编辑器的挂钩在示例场景中看到此行为。

    • 停止手部约束逻辑:尝试将手部约束对象设置为停止 (或未) 激活/停用逻辑运行时,请将 UpdateSolver 设置为 False,而不是禁用 HandConstraintPalmUp。
      • 如果要启用基于凝视的 (甚至非基于凝视的) 重新附加逻辑,请通过调用 HandConstraintPalmUp.StartWorldLockReattachCheckCoroutine () 函数来跟进。 此调用将触发协同例程,然后继续检查是否满足“IsValidController”条件,并在 (或对象) 禁用后,将 UpdateSolver 设置为 True。
    • 启动手部约束逻辑:尝试将手部约束对象设置为再次开始跟随你的手部时(根据是否满足激活条件),将 SolverHandler 的 UpdateSolver 设置为 true。
  • 重新附加逻辑:目前,HandConstraintPalmUp 能够自动将目标对象重新附加到跟踪点,无论 SolverHandler 的 UpdateSolver 是否为 True。 此行为通过调用 HandConstraintPalmUp 的 StartWorldLockReattachCheckCoroutine () 函数进行处理,之后,该函数已 (在本例中,有效将 SolverHandler 的 UpdateSolver 设置为 False) 。

请参阅