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

Unity Oculus VR中通过子对象移动父对象问题求助

通过手柄移动棋盘时出现来回跳动问题

我尝试通过预制体中的手柄(Handle)移动棋盘(ChessBoard),当前代码看似能运行,但棋盘每帧会跳到我身后再返回,一直来回跳动。这是我目前最接近正确实现的版本,求解决建议。

当前代码

using Oculus.Interaction;
using Oculus.Interaction.HandGrab;
using System.Linq;
using UnityEngine;

public class MoveBoardWithHandle : MonoBehaviour
{
    private HandGrabInteractable interactor;
    private Rigidbody board;
    private Rigidbody handle;
    Quaternion initRoataion;

    void Start()
    {
        interactor = GetComponent<HandGrabInteractable>();
        var rigidBodies = GetComponentsInParent<Rigidbody>();
        handle = rigidBodies.FirstOrDefault(x => x.name == "Handle");
        board = rigidBodies.FirstOrDefault(x => x.name == "ChessBoard");
        initRoataion = handle.rotation;
    }

    bool reSetHandleRotation = false;
    
    void Update()
    {
        if(interactor.State == InteractableState.Select)
        {
            Vector3 boardOffset = board.transform.position - handle.transform.position;
            board.transform.position = handle.transform.position -= boardOffset;
            reSetHandleRotation = true;
        }
        else
        {
            if(reSetHandleRotation)
            {
                handle.transform.rotation = initRoataion;
                reSetHandleRotation = false;
            }
        }
    }
}

相关截图

  • 父物体Inspector截图:父物体Inspector截图
  • 子物体Inspector截图:子物体Inspector截图

问题分析与修复方案

核心问题

你在每帧修改了手柄的位置(handle.transform.position -= boardOffset),这和Oculus交互系统对手柄的控制逻辑冲突,导致位置来回跳动。同时直接修改transform.position会绕过物理引擎,容易引发异常行为。

修复代码

using Oculus.Interaction;
using Oculus.Interaction.HandGrab;
using System.Linq;
using UnityEngine;

public class MoveBoardWithHandle : MonoBehaviour
{
    private HandGrabInteractable _handGrabInteractable;
    private Rigidbody _boardRb;
    private Rigidbody _handleRb;
    private Vector3 _boardToHandleOffset; // 棋盘与手柄的初始相对偏移
    private Quaternion _initialHandleRotation;

    void Start()
    {
        _handGrabInteractable = GetComponent<HandGrabInteractable>();
        var rigidBodies = GetComponentsInParent<Rigidbody>();
        _handleRb = rigidBodies.FirstOrDefault(x => x.name == "Handle");
        _boardRb = rigidBodies.FirstOrDefault(x => x.name == "ChessBoard");
        
        if (_boardRb != null && _handleRb != null)
        {
            // 提前记录初始偏移,避免每帧计算出错
            _boardToHandleOffset = _boardRb.transform.position - _handleRb.transform.position;
        }
        _initialHandleRotation = _handleRb.transform.rotation;
    }

    private bool _needResetHandleRotation = false;
    
    void FixedUpdate() // 物理操作放在FixedUpdate更稳定
    {
        if (_handGrabInteractable?.State == InteractableState.Select)
        {
            if (_boardRb != null && _handleRb != null)
            {
                // 根据手柄当前位置+初始偏移,计算棋盘目标位置
                Vector3 targetBoardPos = _handleRb.transform.position + _boardToHandleOffset;
                // 用MovePosition让物理引擎处理移动,避免冲突
                _boardRb.MovePosition(targetBoardPos);
            }
            _needResetHandleRotation = true;
        }
        else
        {
            if (_needResetHandleRotation && _handleRb != null)
            {
                _handleRb.MoveRotation(_initialHandleRotation);
                _needResetHandleRotation = false;
            }
        }
    }
}

额外配置建议

  • 将手柄(Handle)的Rigidbody设置为运动学(Is Kinematic),因为它由Oculus交互系统控制,不需要物理模拟
  • 棋盘(ChessBoard)的Rigidbody可根据需求设置是否运动学,开启重力或碰撞检测,确保物理交互正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:02:45