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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:33:23