Unity中射线检测物体使用Lerp旋转不顺畅的问题排查
问题分析与解决方案
你的旋转效果不符合预期,核心是三个关键错误:
1. 错误构造目标旋转四元数
直接通过new Quaternion()给y分量加90度完全错误——四元数的x/y/z/w不是欧拉角角度值,不能直接修改。必须用Quaternion.Euler()将欧拉角转换为正确的四元数。
2. Lerp仅执行一帧
Input.GetKeyDown(interactionKey)只在按键按下的第一帧返回true,导致Lerp代码只执行一次,物体只会旋转极小角度就停止,无法完成持续过渡。
3. 缺少旋转状态控制
没有标记物体是否正在旋转,再次按下E时会重新设置起始旋转,打断当前旋转过程。
修正后的完整代码
using UnityEngine; public class PlayerInteraction : MonoBehaviour { [Header("相机设置")] public Camera playerCamera; [Header("射线检测")] private Vector3 rayStartPosition; private float lengthOfRay = 5f; private RaycastHit raycastedObject; private GameObject hittedObject; [Header("交互设置")] private KeyCode interactionKey = KeyCode.E; [Header("门旋转设置")] private Quaternion targetOpenRotation; private bool isRotating = false; // 旋转速度,值越大转得越快 public float rotationSpeed = 2f; void Start() { rayStartPosition = new Vector3(Screen.width / 2, Screen.height / 2, 0); } void Update() { CheckForInteractable(); if (isRotating) { RotateObject(); } } // 单独处理射线检测与交互触发 private void CheckForInteractable() { Ray cameraRay = playerCamera.ScreenPointToRay(rayStartPosition); if (Physics.Raycast(cameraRay, out raycastedObject, lengthOfRay) && Input.GetKeyDown(interactionKey) && !isRotating) { hittedObject = raycastedObject.collider.gameObject; // 基于当前欧拉角计算目标旋转(绕Y轴转90度) Vector3 targetEuler = hittedObject.transform.eulerAngles + new Vector3(0, 90, 0); targetOpenRotation = Quaternion.Euler(targetEuler); isRotating = true; } } // 持续执行旋转逻辑 private void RotateObject() { // 使用Time.deltaTime让旋转速度不受帧率影响 hittedObject.transform.rotation = Quaternion.Lerp(hittedObject.transform.rotation, targetOpenRotation, rotationSpeed * Time.deltaTime); // 判断是否接近目标旋转,停止旋转并修正角度 if (Quaternion.Angle(hittedObject.transform.rotation, targetOpenRotation) < 0.1f) { hittedObject.transform.rotation = targetOpenRotation; isRotating = false; } } }
关键修改说明
- 将射线检测与旋转逻辑拆分,职责更清晰
- 用
Quaternion.Euler()正确生成目标旋转四元数 - 添加
isRotating状态标记,避免重复触发旋转 - 使用
Time.deltaTime保证旋转速度在不同帧率下一致 - 增加旋转完成判断,确保物体最终准确到达目标角度
内容的提问来源于stack exchange,提问作者dmitry rubanov
相关产品推荐
相关产品推荐

