You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity XR Interaction Toolkit:如何让单只手松开抓取物体且不影响另一只

Unity VR 单只手强制松开抓取的实现方案

要解决你遇到的问题,核心是主动取消目标手部的选中状态——单纯修改allowSelect或enableInteractions这类参数只会控制是否允许新的抓取操作,不会自动释放已经抓住的物体。以下是具体实现步骤:

核心解决方法

1. 强制取消目标手的抓取状态

直接调用XRBaseInteractor的ClearSelection()方法,这个方法会主动触发物体的OnSelectExit事件,彻底重置手部和物体的交互状态:

// targetHand 是你要处理的那只手的 XRBaseInteractor 组件
targetHand.ClearSelection();

2. 临时禁用交互(可选)

如果需要防止目标手立刻重新抓取原物体,可以在调用ClearSelection后临时禁用交互,等新物体实例化完成后再恢复:

targetHand.allowSelect = false;
// 实例化新物体后再设回 true

3. 实例化新物体并让目标手抓取

实例化预制体后,调用SelectObject()方法让目标手主动抓取新物体:

GameObject newItem = Instantiate(itemPrefab, targetHand.transform.position, targetHand.transform.rotation);
XRGrabInteractable newGrab = newItem.GetComponent<XRGrabInteractable>();
if (newGrab != null)
{
    // 建议等待一帧再执行抓取,确保状态完全重置
    StartCoroutine(DelaySelect(targetHand, newGrab));
}

IEnumerator DelaySelect(XRBaseInteractor hand, XRGrabInteractable grabObj)
{
    yield return null;
    hand.allowSelect = true;
    hand.SelectObject(grabObj);
}

完整示例代码

以下是检测双手分开距离触发复制的完整逻辑:

using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using System.Collections;

public class ItemDuplicator : MonoBehaviour
{
    public XRBaseInteractor leftHand;
    public XRBaseInteractor rightHand;
    public GameObject itemPrefab;
    public float splitDistanceThreshold = 0.3f; // 触发复制的双手距离阈值

    private GameObject currentGrabbedItem;

    void Update()
    {
        // 检测是否双手抓取了同一个物体
        if (leftHand.selectedObject != null && rightHand.selectedObject != null 
            && leftHand.selectedObject == rightHand.selectedObject)
        {
            currentGrabbedItem = leftHand.selectedObject;
            float handDistance = Vector3.Distance(leftHand.transform.position, rightHand.transform.position);

            // 达到距离阈值时执行复制
            if (handDistance >= splitDistanceThreshold)
            {
                // 选择要松开的手(这里以右手为例)
                XRBaseInteractor targetHand = rightHand;

                // 1. 强制松开原物体
                targetHand.ClearSelection();

                // 2. 临时禁用交互
                targetHand.allowSelect = false;

                // 3. 实例化新物体并让目标手抓取
                GameObject newItem = Instantiate(itemPrefab, targetHand.transform.position, targetHand.transform.rotation);
                XRGrabInteractable newGrab = newItem.GetComponent<XRGrabInteractable>();
                if (newGrab != null)
                {
                    StartCoroutine(DelaySelect(targetHand, newGrab));
                }

                // 重置检测,避免重复触发
                currentGrabbedItem = null;
            }
        }
    }

    IEnumerator DelaySelect(XRBaseInteractor hand, XRGrabInteractable grabObj)
    {
        yield return null;
        hand.allowSelect = true;
        hand.SelectObject(grabObj);
    }
}

关键注意事项

  • 确保被抓取物体的XRGrabInteractable组件中,Allow Multiple Grabbers选项已勾选,这样双手才能同时抓取同一个物体。
  • 不要直接销毁原物体再实例化,这会导致交互状态混乱,必须先通过ClearSelection释放抓取,再处理新物体。
  • 如果使用的是XR Interaction Toolkit的新版本,API可能略有调整,但核心逻辑都是主动调用取消选择的方法。

内容的提问来源于stack exchange,提问作者Okuromatsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:52:52