开发

互动设置

更新时间: 2026年3月13日
推荐 Unity 开发者采用互动 SDK 来集成手势追踪,该方法提供标准化的互动和手势。不使用此 SDK 构建自定义互动将带来巨大挑战,而且很难在商店中获得批准。
在使用双手作为输入模态时,要构建丰富的体验,就需要考虑对象的放置方式,将多种互动结合起来。近场对象在手臂可及的范围内。戳或捏拉等直接互动方式对这些对象非常有效。远场对象在手臂可及范围之外,需要进行光线投射,将光线投射至远处的对象。这与 Touch 控制器的互动非常相似。
戳和捏拉是实时手势,任何用户都能运用它们非常直观地执行基本任务,如设置焦点、选择或操纵空间中的对象。戳这个手势需要用户伸出手指并朝着对象移动,直到手指与空间中的对象发生碰撞。捏拉可以与直接互动和光线投射互动方法一起使用。将手移向对象以引导光线投射,然后捏住以选择或抓取对象。
OVR SkeletonOVR Hand API 提供在 VR 中将用户的真实双手渲染为完全可活动的再现形式所需的信息,无需使用控制器,这些信息包括:
  • 骨骼信息
  • 手和手指的位置与方向
  • 捏拉力度
  • 用户界面光线投射的指针姿势
  • 追踪置信度
  • 手部大小
  • 打开通用菜单的系统手势
以下各部分将介绍集成手部输入的几种功能的实现情况:

获取骨骼编号

OVR Skeleton 包含完整的骨骼编号列表和实现互动的方法,例如检测手势、计算手势置信度、定位特定骨骼或触发物理系统中的碰撞事件。
调用 GetCurrentStartBoneID()GetCurrentEndBoneId() 方法可返回开始和结束骨骼编号,主要用于迭代当前配置的骨骼类型中存在的骨骼编号子集。调用 GetCurrentNumBones()GetCurrentNumSkinnableBones() 方法可返回骨架中骨骼的总数和可覆皮骨骼的总数。骨骼和可覆皮骨骼的区别在于,骨骼还包括指尖的锚点。不过,就网格或动画而言,它们实际上并不是手部骨骼的一部分,而可覆皮骨骼则过滤掉了指尖。
自 71 版本起,核心 SDK 增加了对 Open XR Hand Skeleton 的支持,该骨架的数量和排列方式都有所不同。您需要使用的骨骼编号取决于您使用的是 OVR Hand Skeleton 还是 Open XR Hand Skeleton。如需了解具体差异,请参阅 Hand Skeleton 版本

OVR Hand Skeleton 骨骼

Invalid          = -1
Hand_Start       = 0
Hand_WristRoot   = Hand_Start + 0 // root frame of the hand, where the wrist is located
Hand_ForearmStub = Hand_Start + 1 // frame for user's forearm
Hand_Thumb0      = Hand_Start + 2 // thumb trapezium bone
Hand_Thumb1      = Hand_Start + 3 // thumb metacarpal bone
Hand_Thumb2      = Hand_Start + 4 // thumb proximal phalange bone
Hand_Thumb3      = Hand_Start + 5 // thumb distal phalange bone
Hand_Index1      = Hand_Start + 6 // index proximal phalange bone
Hand_Index2      = Hand_Start + 7 // index intermediate phalange bone
Hand_Index3      = Hand_Start + 8 // index distal phalange bone
Hand_Middle1     = Hand_Start + 9 // middle proximal phalange bone
Hand_Middle2     = Hand_Start + 10 // middle intermediate phalange bone
Hand_Middle3     = Hand_Start + 11 // middle distal phalange bone
Hand_Ring1       = Hand_Start + 12 // ring proximal phalange bone
Hand_Ring2       = Hand_Start + 13 // ring intermediate phalange bone
Hand_Ring3       = Hand_Start + 14 // ring distal phalange bone
Hand_Pinky0      = Hand_Start + 15 // pinky metacarpal bone
Hand_Pinky1      = Hand_Start + 16 // pinky proximal phalange bone
Hand_Pinky2      = Hand_Start + 17 // pinky intermediate phalange bone
Hand_Pinky3      = Hand_Start + 18 // pinky distal phalange bone
Hand_MaxSkinnable= Hand_Start + 19
// Bone tips are position only. They are not used for skinning but are useful for hit-testing.
// NOTE: Hand_ThumbTip == Hand_MaxSkinnable since the extended tips need to be contiguous
Hand_ThumbTip    = Hand_Start + Hand_MaxSkinnable + 0 // tip of the thumb
Hand_IndexTip    = Hand_Start + Hand_MaxSkinnable + 1 // tip of the index finger
Hand_MiddleTip   = Hand_Start + Hand_MaxSkinnable + 2 // tip of the middle finger
Hand_RingTip     = Hand_Start + Hand_MaxSkinnable + 3 // tip of the ring finger
Hand_PinkyTip    = Hand_Start + Hand_MaxSkinnable + 4 // tip of the pinky
Hand_End         = Hand_Start + Hand_MaxSkinnable + 5
Max              = Hand_End + 0

OpenXR Hand Skeleton 骨骼

XRHand_Start                = 0,
XRHand_Palm                 = 0,
XRHand_Wrist                = 1,
XRHand_ThumbMetacarpal      = 2,
XRHand_ThumbProximal        = 3,
XRHand_ThumbDistal          = 4,
XRHand_ThumbTip             = 5,
XRHand_IndexMetacarpal      = 6,
XRHand_IndexProximal        = 7,
XRHand_IndexIntermediate    = 8,
XRHand_IndexDistal          = 9,
XRHand_IndexTip             = 10,
XRHand_MiddleMetacarpal     = 11,
XRHand_MiddleProximal       = 12,
XRHand_MiddleIntermediate   = 13,
XRHand_MiddleDistal         = 14,
XRHand_MiddleTip            = 15,
XRHand_RingMetacarpal       = 16,
XRHand_RingProximal         = 17,
XRHand_RingIntermediate     = 18,
XRHand_RingDistal           = 19,
XRHand_RingTip              = 20,
XRHand_LittleMetacarpal     = 21,
XRHand_LittleProximal       = 22,
XRHand_LittleIntermediate   = 23,
XRHand_LittleDistal         = 24,
XRHand_LittleTip            = 25,
XRHand_Max                  = 26,
XRHand_End                  = 26,

添加互动

为了标准化跨应用的互动,OVR Hand 提供对经筛选的指针姿势和捏拉手势检测的访问,以确保您的应用遵循与 Oculus 系统应用相同的互动模型。只需指向和点击互动的简单应用可以使用指针姿势,将手当做简单的指向设备,并将捏拉手势作为点击操作。
Pointer pose and pinch selection

捏拉

捏拉是使用手进行用户界面互动的基本互动原型。当指尖与拇指相触时,即触发捏拉。成功用食指完成捏拉,等同于控制器上的选择或触发操作,可激活按钮或其他 UI 控件。
OVR 手势为每根手指提供两种独立的捏拉数值:布尔状态与连续强度。布尔状态表示手指当前是否正在捏拉。连续强度以 0(无接近)到 1(相触)的归一化值报告指尖与拇指的接近程度。这些是来自原生运行时的独立值,并非互相推导而来。
HandFinger 枚举中的可用常量包括 ThumbIndexMiddleRingPinky。对于 IndexMiddleRingPinky,捏拉通过该手指指尖与拇指的接近程度进行判定。Thumb 值是一个特例:其捏拉强度返回其余四根手指的最大捏拉强度;若任意一根手指正在捏拉,其布尔捏拉状态会返回 true。

检测捏拉状态(布尔值)

调用 GetFingerIsPinching() 并传入手指常量,可检查该手指当前是否正在捏拉。此方法会返回一个布尔值。捏拉阈值由 Oculus 运行时决定,无法通过 C# 配置。
此方法适用于离散事件,例如拿取检测、按钮选择或触发操作。

读取捏拉强度(浮点数)

调用 GetFingerPinchStrength() 并传入手指常量,可读取当前捏拉手势的强度。返回值范围为 0 到 1,0 表示未捏拉,1 表示指尖与拇指相触。
此方法适用于连续或模拟反馈,例如控制发光强度、调整光标大小或驱动混合形状。

检查手指置信度

调用 GetFingerConfidence() 并传入手指常量,可检查手指姿势的置信度等级。此方法会返回 TrackingConfidence.LowTrackingConfidence.High,表示追踪系统对手指姿势的置信度。在响应捏拉数据前检查置信度,以避免对不可靠的输入做出反应。
var hand = GetComponent<OVRHand>();
bool isIndexFingerPinching = hand.GetFingerIsPinching(HandFinger.Index);
float indexFingerPinchStrength = hand.GetFingerPinchStrength(HandFinger.Index);
TrackingConfidence confidence = hand.GetFingerConfidence(HandFinger.Index);

指针姿势

从受追踪的手部得出稳定的指向方向并非一项简单的任务,其中涉及筛选、手势检测和其他因素。OVR Hand 提供一个指针姿势,有助于在 Meta Quest 应用中实现一致的指向互动。这个姿势会指示追踪空间中指向光线的起点和位置。我们强烈建议您使用 PointerPose 来确定用户在进行用户界面互动时指向的方向。
Pointer pose graphic
指针姿势可能有效,也可能无效,具体取决于用户的手部位置、追踪状态和其他因素。调用 IsPointerPoseValid 属性可检查指针姿势是否有效。如果有效,则将光线用于用户界面命中测试,否则避免将其用于渲染光线。

手部追踪置信度

在任何时候,您都有可能想要检查应用是否能检测到手部。调用 IsTracked 属性可验证手部当前是否可见且未被遮挡,可由头戴设备追踪。如要检查追踪系统对整体手部姿势的置信度,请调用 HandConfidence 属性,这个属性会返回 LowHigh 作为置信度。我们建议仅在手部可见且置信度较高时使用手部姿势数据进行渲染和互动。

获取手部大小

调用 HandScale 属性可获取用户手部的大小(相较于默认手部模型大小 1.0)。这个属性会返回一个浮点值,作为与手部模型相比的大小。例如,1.05 表示用户的手部尺寸比默认手部模型大 5%。这个值可能随时更改,您应使用此值缩放手部,以便在运行时进行渲染和互动模拟。

检查系统手势

系统手势是一种保留手势,用户可使用它过渡到 Meta Quest 通用菜单。当用户将惯用手抬起,手掌面向用户自己,并用食指捏拉时,就会发生这种行为。开始捏拉时,捏合的手指会变成淡蓝色。当用户使用非惯用手执行手势时,会触发 Button.Start 事件。您可以轮询 Button.Start,以便在应用逻辑中集成按钮按下事件的任何操作。
如要检测惯用手,请调用 IsDominantHand 属性。如果结果为 true,则通过调用 IsSystemGestureInProgress 属性检查用户是否正在执行系统手势。我们建议,如果系统手势正在进行中,应用应向用户提供视觉反馈,例如用不同的颜色或高亮显示呈现手部材质,向用户表明系统手势正在进行中。当用户正在执行系统手势时,应用还应暂停处理任何自定义手势。这样,当用户打算过渡到 Meta Quest 通用菜单时,应用就可以避免触发基于手势的事件。

详细了解

设计指南