如何在Unity C#中抓取固定位置物体并随Oculus Quest控制器旋转
Oculus Quest 仅跟随控制器旋转的抓取功能实现修正
原代码的核心问题
- 存在未声明的悬空变量:代码中调用的
taregt_eulerAngX、taregt_eulerAngY、target_eulerAngZ无任何定义,无法通过编译 - 未读取控制器真实姿态:已经将场景内控制器对象设为target,却全程没有获取target对应的旋转值,目标旋转值的计算逻辑完全缺失
- 欧拉角使用错误:通过
eulerAngles计算旋转、做插值时,会因为欧拉角360度环绕的数值跳变,出现旋转失控、抖动、不跟手的问题 - 插值逻辑错误:Lerp方法的传入系数为
Time.time * speed,该值会随运行时间持续增大,超过1后会跳过平滑过程直接硬切旋转值,无法实现匀速平滑旋转 - 缺少跟手持续触发逻辑:设置了旋转距离阈值,只要当前旋转和目标值的差值小于阈值就停止更新,不符合按住抓取按钮时持续跟随的预期
可直接运行的修正代码
[Header("控制器参数配置")] // 指定要追踪的控制器,默认左手 public OVRInput.Controller trackedController = OVRInput.Controller.LTouch; // 绑定抓取触发按键 public OVRInput.Button grabButton; [Tooltip("旋转平滑速度,数值越高跟手响应越快")] [Range(1f, 15f)] public float followRotateSpeed = 6f; private void Update() { // 抓取按键按下时执行旋转同步 if (OVRInput.Get(grabButton, trackedController)) { // 直接获取OVR插件提供的控制器实时旋转值 Quaternion currentControllerRot = OVRInput.GetLocalControllerRotation(trackedController); // 仅同步旋转,全程不修改transform.position,保证物体位置固定不动 transform.rotation = Quaternion.Lerp( transform.rotation, currentControllerRot, Time.deltaTime * followRotateSpeed ); } }
适配优化提示
- 如果不希望抓取瞬间物体直接翻转对齐控制器的世界坐标系初始朝向,可以在抓取触发的第一帧,记录物体和控制器的初始旋转差值:
Quaternion offset = Quaternion.Inverse(controllerRot) * transform.rotation,后续每帧赋值旋转时计算目标值为offset * controllerRot,让物体从原有姿态平滑跟随控制器旋转,不会出现突兀的角度跳转 - 无需在场景中手动拖拽绑定控制器GameObject引用,通过OVRInput的内置接口直接读取控制器数据,可避免对象引用丢失、追踪错位的问题
- 物体如需保持位置完全固定,不需要额外添加刚体的位置约束——只要代码逻辑中从不修改transform.position属性,物体就不会发生平移
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

