IHand 的 HandRef。该 Prefab 上的其他组件通过此引用读取手部状态。ShapeRecognizerActiveState 组件,在满足指定形状的标准时会变为激活状态。TransformRecognizerActiveState,在检测到变换特征(如特定的手腕方向)时会变为激活状态。ActiveStateGroup,当所有依赖的 ActiveStates 为 true 时返回 true。SelectorUnityEventWrapper 和 ActiveStateSelector,在检测到姿势时可以调用事件。
TransformRecognizerActiveState 中,还包括形状特征,这些形状特征包含在 ShapeRecognizerActiveState 中。这些变换和形状特征通过 ActiveStateGroup 进行组合,以定义姿势。ShapeRecognizerActiveState 会将构成姿态的形状与每根手指的状态进行比对。如果它们全部匹配,ShapeRecognizerActiveState 就会变为启用。ShapeRecognizer 是一个用于定义形状的 ScriptableObject。为了定义形状,它使用一组称为“特征配置”的规则。“特性配置”为五根手指中的每一根都指定了一个必需的位置(状态)。它通过使用至少一个手指特征(卷曲度、屈曲度、外展度和对掌度)来定义状态。ShapeRecognizer由 ShapeRecognizerActiveState 组件引用,以确定某个姿势是否处于启用状态。FingerFeatureStateProvider 提供追踪到的手部各手指的状态,并包含每个手指状态转换的阈值。它由 ShapeRecognizerActiveState 组件引用。FingerFeatureStateThresholds 是一个 ScriptableObject,用于定义每个手指特征的状态阈值。状态阈值是一组边界值,用于确定手指何时从一个状态过渡到另一个状态。例如,卷曲特征有三种状态:张开、中立和闭合。卷曲特征的状态阈值使用角度(以度为单位)来定义手指状态从张开变为中立、从中立变为闭合,或者相反的情况。DefaultSettings/PoseDetection 下:




定义手部手指、手腕和手掌的轴线。TransformRecognizerActiveState 接收一个 TransformFeatureStateProvider、一组变换特征配置以及一个变换配置。该状态提供器会读取原始特征值,并使用您在此组件中提供的 TransformConfig 将它们量化为 TransformFeatureStates。TransformFeatureStateProvider 提供被追踪手部的变换状态。它被 TransformRecognizerActiveState 组件所引用。RegisterConfig 方法就可以查询该配置下追踪的每个特征的状态。它借助 FeatureStateProvider 来驱动状态变更逻辑。JointDeltaProvider 是一个组件,用于追踪各帧之间的手部关节的位置,并计算帧到帧的位置和旋转差异。它会缓存关节姿态数据,以避免当多个组件需要同一关节的差异信息时进行重复计算。JointVelocityActiveState 和 JointRotationActiveState 均需引用 JointDeltaProvider 以访问关节运动数据。提供器仅追踪由活跃使用者注册的关节,尽量减少性能开销。| 属性 | 说明 |
|---|---|
手部 | 追踪手部,每帧从中读取关节姿态数据 |
JointVelocityActiveState 是一个 IActiveState,用于追踪一系列手部关节的位置速度,并将其与目标方向进行比较。当目标轴向上的速度超过阈值并持续达到最短设定时长时,该状态将会激活。| 属性 | 说明 |
|---|---|
手部 | 提供关节位置的追踪手部 |
关节增量提供器 | JointDeltaProvider 用于检索缓存的位置增量 |
功能配置 | 需评估的关节及其目标轴列表 |
最小速度 | 状态激活所需超过的单位(每秒)速度阈值 |
阈值范围 | 为速度阈值设置的迟滞缓冲范围,避免在临界值附近频繁切换状态 |
状态最短持续时间 | 状态变化前,速度超过阈值的最短持续时间(单位:秒) |
JointRotationActiveState 是一个 IActiveState,用于追踪一系列手部关节的角速度,并将其与目标旋转轴进行比较。当围绕目标轴的角速度超过阈值并持续达到最短设定时长时,该状态将会激活。| 属性 | 说明 |
|---|---|
手部 | 提供关节旋转的追踪手部 |
关节增量提供器 | JointDeltaProvider 用于检索缓存的旋转增量 |
功能配置 | 需评估的关节及其目标旋转轴列表 |
每秒度数 | 状态激活所需超过的角速度阈值(单位:度/秒) |
阈值范围 | 为角速度阈值设置的迟滞缓冲范围,避免在临界值附近频繁切换状态 |
状态最短持续时间 | 状态变化前,角速度必须超过阈值的最短持续时间(单位:秒) |
IActiveState 组件可以使用 Sequence 组件串联在一起。由于 Sequence 组件可识别一段时间内的一系列 IActiveState,因此可用于组成复杂的手势。有关复杂手势的示例,请参阅手势示例示例场景。Sequence 接收一个 ActivationSteps 列表,并在它们启用时逐个执行。每个 ActivationStep 包含 IActiveState、最小启用时长和最大步骤时长。这些步骤的运作如下:IActiveState 的启用时长必须至少达到最小启用时长,Sequence 才会进入下一步。IActiveState 的启用时长超过最大步骤时长,则步骤会失败,Sequence 会重新开始。Sequence 中的最后一个 ActivationStep 完成,Sequence 就会启用。如果提供了一个可选的 RemainActiveWhile IActiveState,则只要 RemainActiveWhile 保持启用,Sequence 就会保持启用。Sequence 的最后一个阶段是可选的冷却阶段,其持续时间可在 RemainActiveCooldown 字段中设置。停用中的 Sequence 会等待这个冷却计时器结束,然后才最终变为非启用状态。ActiveStateDebugTreeUI 组件会在世界空间用户界面画布上实时渲染任何 IActiveState 层级的可视化树状图。树中的每个节点代表一个 IActiveState 组件,并显示其当前是处于激活还是未激活状态。通过该组件,您可以直观看到姿势或手势序列中哪些部分已被识别,哪些部分还未被识别。ActiveStateDebugTreeUI 基于 IActiveState 接口运行,因此可用于调试项目中的任何 IActiveState 层级,而不仅仅是姿势。例如,您可以指定 ActiveStateGroup、Sequence 或任何自定义 IActiveState 作为根,来实现状态树可视化。Packages/com.oculus.integration.interaction/Runtime/Prefabs/Debug/ 中的 ActiveStateDebugTree prefab 添加到您的场景。ActiveStateDebugTreeUI 组件中,指定要调试的根 IActiveState,例如 ActiveStateGroup 或 Sequence。IActiveState 节点,并通过颜色来区分当前的激活或未激活状态。| 属性 | 说明 |
|---|---|
激活状态 | 根节点 IActiveState,其树状结构将可视化 |
节点 prefab | 用于渲染树中每个节点的 prefab |
FeatureStateProvider 是一个通用辅助类,用于跟踪功能的当前状态,并使用阈值来确定状态变化。该类使用缓冲区来处理状态变化,以确保特征不会在状态之间快速切换。IFeatureStateThreshold 是一个泛型接口,它定义了手部姿态检测中使用的所有阈值的功能。IFeatureStateThresholds 定义了一个特定于特征类型(无论是手指特征还是变换特征)的 IFeatureStateThreshold 集合。IFeatureThresholds 提供了一个接口,该接口包含一组 IFeatureStateThreshold 以及 MinTimeInState(即特征在过渡到另一个状态之前可以处于某个状态的最小时间阈值)。IActiveState,用于检测手部关节是否位于碰撞器内部。如果指定 SphereCollider,则使用其半径进行检查;否则,脚本将依赖于碰撞器的边界。如果开发者希望在姿势处于启用状态时检查手部关节是否存在于某个体积内,那么这个类就很有用。ColliderContainsHandJointActiveState 相结合,以将碰撞器相对于中心眼进行定位。