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

Steam VR Unity中如何获取手持物体的Rigidbody质量?

Unity VR 获取手持物体质量实现方案

基础前提

假设你使用Unity官方的XR Interaction Toolkit(新手VR开发首选框架),先确保已完成基础XR环境配置(添加XR Origin、左右手控制器并绑定交互组件)。

步骤1:可抓取物体的基础设置

给需要被抓取的物体添加以下组件:

  • Rigidbody:勾选Use Gravity,设置合适的Mass数值(比如1、5、10),若需抓取时固定物体,可在抓取时临时关闭重力/冻结位置旋转(代码中已提供可选逻辑)
  • XR Grab Interactable:将控制器的XR Ray Interactor或Direct Interactor添加到该组件的Interaction Layer Mask中,确保能被手柄抓取

步骤2:核心代码实现

创建一个名为GrabMassTracker的C#脚本,挂载到**任意XR Controller(手柄)**上,代码如下:

using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class GrabMassTracker : MonoBehaviour
{
    // 存储当前手持物体的质量
    private float currentHeldMass = 0f;

    private XRController _xrController;

    void Awake()
    {
        // 获取手柄的XR Controller组件
        _xrController = GetComponent<XRController>();
        if (_xrController == null)
        {
            Debug.LogError("当前GameObject没有XR Controller组件,请挂载到手柄上!");
            return;
        }
    }

    void OnEnable()
    {
        // 监听手柄的抓取/释放事件
        if (_xrController.interactor is ISelectInteractor selectInteractor)
        {
            selectInteractor.selectEntered.AddListener(OnGrabObject);
            selectInteractor.selectExited.AddListener(OnReleaseObject);
        }
    }

    void OnDisable()
    {
        // 移除监听,避免内存泄漏
        if (_xrController.interactor is ISelectInteractor selectInteractor)
        {
            selectInteractor.selectEntered.RemoveListener(OnGrabObject);
            selectInteractor.selectExited.RemoveListener(OnReleaseObject);
        }
    }

    // 抓取物体时触发
    void OnGrabObject(SelectEnterEventArgs args)
    {
        // 获取被抓取物体的Rigidbody组件
        Rigidbody grabbedRigidbody = args.interactableObject.transform.GetComponent<Rigidbody>();
        
        if (grabbedRigidbody != null)
        {
            // 记录当前物体质量
            currentHeldMass = grabbedRigidbody.mass;
            Debug.Log($"当前手持物体质量:{currentHeldMass} kg");
            
            // 可选:抓取时冻结物体,避免物理晃动(根据需求开启)
            grabbedRigidbody.isKinematic = true;
        }
        else
        {
            Debug.LogWarning("被抓取的物体没有Rigidbody组件,无法获取质量!");
            currentHeldMass = 0f;
        }
    }

    // 释放物体时触发
    void OnReleaseObject(SelectExitEventArgs args)
    {
        // 可选:释放时恢复物体物理属性
        Rigidbody releasedRigidbody = args.interactableObject.transform.GetComponent<Rigidbody>();
        if (releasedRigidbody != null)
        {
            releasedRigidbody.isKinematic = false;
        }
        
        // 重置当前手持质量
        currentHeldMass = 0f;
        Debug.Log("已释放物体,当前手持质量:0 kg");
    }

    // 提供外部获取当前质量的方法(比如给UI显示用)
    public float GetCurrentHeldMass()
    {
        return currentHeldMass;
    }
}

步骤3:测试验证

  1. 给场景中的可抓取物体设置不同的Rigidbody.mass值
  2. 进入Play模式,用手柄抓取物体,查看Console面板会输出当前物体的质量
  3. 如果需要在UI上显示质量,只需调用GrabMassTracker.GetCurrentHeldMass()方法获取数值即可

非XRIT框架适配(比如VRTK)

核心逻辑通用:

  • 监听手柄的抓取开始和抓取结束事件
  • 在抓取事件中获取被抓物体的Rigidbody.mass并存储
  • 释放时重置数值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:50:46