手部指导 - MRTK2
手部指导是一个 3D 建模的手部,在系统未检测到用户的手部时触发。 此功能是作为“教学”组件实现的,可在尚未传授手势时帮助指导用户。 如果用户在一段时间内未执行指定的手势,手部将以某种延迟循环。 手部指导可用于表示按下按钮或选取全息影像的操作。
当前的交互模型代表各种手势控件,例如滚动、远距选择和近距点击。 下面是现有手部指导示例的完整列表:
- 近距点击 – 用于按钮或近距可交互对象
- 远距选择 – 用于远处的对象
- 移动 – 用于在空间中移动全息影像
- 旋转 – 用于展示如何旋转全息影像或对象
- 缩放 – 用于展示如何将全息影像放大或缩小
- 翻手 – 用于调出 UI 开始面板或手部菜单
- 掌心向上 – 用于开箱即用体验中的光芒时刻。 另一个建议可能是调出 UI 开始面板
- 滚动 – 用于滚动列表或长文档
示例场景
可以在 MixedRealityToolkit.Examples/Experimental/HandCoach/Scenes 下的 HandCoachExample 场景中找到示例
手部 3D 资产
可以在 MixedRealityToolkit.SDK/Experimental/HandCoach 下找到资产
质量
如果在蒙皮网格上注意到失真,需要确保项目使用了适当数量的关节。 转到 Unity 的“编辑”>“项目设置”>“质量”>“其他”>“混合权重”。 确保选择“4 个骨骼”以查看“平滑关节”。
脚本
交互提示
InteractionHint.cs
脚本提供包装器功能,用于触发手部装备的动画和淡入淡出。
如何设置交互提示
若要设置交互提示,建议使用提供的预制件“StaticHandCoachRoot_L.prefab”和“StaticHandCoachRoot_R.prefab”。 此预制件包含 InteractionHint 脚本和手部装备以及适当的层次结构,以确保提供的提示动画按预期工作。 否则,需要通过动画程序将脚本放置在比手部装备高一个父级的 gameObject 上。
检查器属性
HideIfHandTracked:此布尔值指定在跟踪用户的手部时是否应使用手部跟踪状态来隐藏视觉效果。 如果此属性设置为 false,则只会使用脚本属性“customShouldHideVisuals”来确定是否隐藏提示。
MinDelay:此属性指定显示视觉效果的最小延迟。 默认情况下,如果未跟踪用户的手部,则手部的视觉效果将在经过这么多秒后出现。
MaxDelay:此属性指定显示视觉效果的最大延迟。 默认情况下,即使正在跟踪用户的手部,则手部的视觉效果在经过这么多秒后也会出现。
UseMaxTimer:如果此布尔值设置为 false,则会禁用最大计时器,并且仅在用户的手部超出视场范围或自定义条件返回 false 时,才允许显示手部提示。
Repeats:此属性控制在经过最小或最大计时器时提示动画播放的次数。 然后提示将会隐藏并再次等待延迟。
AutoActivate:如果此布尔值设置为 true,当脚本的 GameObject 在层次结构中处于活动状态且脚本已启用时,提示将自动通过计时器逻辑运行。 如果你打算通过代码手动控制提示的出现和消失,则只能将其设置为 false。
AnimationState:当提示处于活动状态时应播放的动画状态的名称。 必须在调用 StartHintLoop() 函数之前设置此属性(如果选中了 AutoActivate,则在 OnEnable 期间设置)。
通过脚本控制 InteractionHint
- StartHintLoop:此函数启动显示/隐藏循环;如果 AutoActivate 标志设置为 true,则启动 OnEnable。
- StopHintLoop:如果当前不在播放,此函数会调用淡出动画状态,然后停用显示/隐藏循环,并在层次结构中将手部装备设置为非活动状态。
- AnimationState:此字符串确定循环期间播放的动画状态。 可以更改此字符串以更改播放的状态,但必须在调用 StopHintLoop 之后这样做,并且必须在更改状态后再次调用 StartHintLoop。
- CustomShouldHideVisuals:你可以使用自己的函数进行此项设置,当你想要隐藏手部视觉效果时,该函数应返回 true(请注意 MinMaxTimer,具体而言,是最大参数)
自定义动画注意事项
淡入淡出的默认值为 0.5 秒,因此为创建的、与装备配合使用的任何自定义动画应至少为 1.5 秒,这样才能传达任何有意义的信息
提供的默认淡入淡出状态,可以通过更改第二个关键帧的时间戳设置淡入淡出长度,来调整 Fade_In 和 Fade_Out。
动画程序和脚本的设置方式应尽量简化设置。 若要添加新的动画状态,只需导入 fbx,确保使用不同的名称设置动画名称,然后将该动画拖放到动画程序中。
MoveToTarget
MoveToTarget.cs 脚本提供在不同的时间将手部提示从跟踪位置移到目标位置的功能。
如何设置 MoveToTarget
提供的预制件“MovingHandCoachRoot_L.prefab”和“MovingHandCoachRoot_R.prefab”在其层次结构中包含一个 MoveToTarget。 如果你想在自己的设置中使用此脚本,需要将其放置在包含装备的动画程序的根 GameObject 上。
检查器属性
- TrackingObject:使用希望装备在开始运动之前要跟随的对象设置此属性。 建议创建一个空的 GameObject 并将其移到特定位置,以帮助精确定位跟踪。
- TargetObject:使用希望装备在运动过程中要移到的对象来设置此属性。 建议创建一个空的 GameObject 并将其移到特定位置,以帮助精确定位跟踪。
- RootObject:将此属性设置为跟踪对象与目标对象之间的共享父级,以便可以正确计算相对位置。 包含的预制件在其层次结构中同时具有跟踪对象和目标对象,但你可以将目标对象设置为预制件以外的 gameObject,并将根对象更改为共享父级。
- Duration:从 TrackingObject 移到 TargetObject 所需的时间,以秒为单位。
- TargetOffset:使 GameObject 到达正确目标位置的可调偏移量。 如果你的动画在动画显示期间包含位置偏移量,则此属性非常有用。
- AnimationCurve:默认为线性曲线,但你可以更改曲线,以便在启动和停止运动路径时提供缓入/缓出。
通过脚本控制 MoveToTarget
在自定义脚本中,可以在希望手部装备跟随 TrackingObject 时调用 Follow(),然后在希望手部装备开始向 TargetObject 运动时调用 MoveToTargetPosition()。
通过动画控制 MoveToTarget
在需要移动的动画中设置两个事件:一个事件包含 Follow() 调用,另一个事件包含 MoveToTargetPosition() 调用。 应在第一个关键帧上设置 Follow,由于它会导致手部装备跟随 TrackingObject。 应在你希望装备从中开始移到目标的关键帧上设置 MoveToTargetPosition。 这就是在提供的预制件中使用脚本功能的方式。
RotateAroundPoint
RotateAroundPoint.cs 脚本提供在不同时间围绕枢轴点旋转手部提示的功能。
如何设置 RotateAroundPoint
提供的预制件“RotatingHandCoachRoot_L.prefab”和“RotatingHandCoachRoot_R.prefab”在其层次结构中包含一个 RotateAroundPoint。 如果你想在自己的设置中使用此脚本,需要将其放置在包含装备的动画程序的根 GameObject 上。
检查器属性
- CenteredParent:使用希望装备在旋转时所围绕的父对象设置此属性。
- InverseParent:使用要与 centeredParent 相反方向旋转的父级(使手部方向保持相同)设置此属性。 一般情况下,这是对其使用了 InteractionHint 脚本的父对象。
- PivotPosition:将此属性设置为希望提示从其开始移动的点。
- Duration:应该围绕 CenteredParent 旋转的时长(以秒为单位)。
- AnimationCurve:默认为线性曲线,但你可以更改曲线,以便在启动和停止运动路径时提供缓入/缓出。
- RotationVector:沿每个轴旋转多少度。
通过脚本控制 RotateAroundPoint
在自定义脚本中,当你希望手部装备开始围绕 CenteredParent 旋转时,请调用 RotateToTarget()。 当你希望位置重置为原始 PivotPosition 时,请调用 ResetAndDeterminePivot()。
通过动画控制 RotateAroundPoint
在需要移动的动画中设置两个事件:一个事件包含 ResetAndDeterminePivot() 调用,另一个事件包含 RotateToTarget() 调用。 应在第一个关键帧上设置 ResetAndDeterminePivot,因为它会导致手部装备重置为 PivotPosition。 应在你希望装备从中开始围绕 CenteredParent 旋转的关键帧上设置 RotateToTarget。 这就是在提供的预制件中使用脚本功能的方式。