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

如何让Quaternion.RotateTowards()实现平滑旋转而非瞬间旋转?

解决Quaternion.RotateTowards瞬间旋转问题及X轴鼠标旋转限制

问题根源

  • RotateTowards参数顺序错误:你将目标旋转(CubeObj的rotation)放在第一个参数位置,但该方法第一个参数应为当前旋转状态,第二个才是目标旋转。参数颠倒导致直接跳转到目标姿态,无法实现平滑过渡。
  • 目标旋转逻辑混淆:用鼠标累积的rotation.x生成目标四元数,与“自动转向CubeObj”的需求冲突,应基于CubeObj的方位生成目标朝向,再叠加鼠标的有限调整。
  • 鼠标输入与自动转向逻辑耦合:当前代码同时处理鼠标累积旋转和自动转向,导致逻辑混乱,既无法实现平滑转向,也不能正确限制X轴旋转范围。

修正代码示例

首先在类中新增变量存储目标水平旋转:

private Quaternion targetHorizontalRotation;

修改clampHorizontalRotation方法:

void clampHorizontalRotation() 
{
    // 1. 处理垂直轴旋转(保留原有限制逻辑)
    float mouseY = Input.GetAxis(yAxis) * sensitivity;
    rotation.y += mouseY;
    rotation.y = Mathf.Clamp(rotation.y, -yRotationLimit, yRotationLimit);
    var yQuat = Quaternion.AngleAxis(rotation.y, Vector3.left);
    transform.localRotation = yQuat;

    // 2. 计算朝向CubeObj的水平目标旋转(忽略垂直高度差)
    Vector3 lookDir = climbing.CubeObj.transform.position - player.transform.position;
    lookDir.y = 0;
    Quaternion desiredTargetRot = Quaternion.LookRotation(lookDir);

    // 3. 平滑过渡到目标旋转(实现自动转向效果)
    targetHorizontalRotation = Quaternion.RotateTowards(
        targetHorizontalRotation, 
        desiredTargetRot, 
        rotationSpeed * Time.deltaTime
    );

    // 4. 处理鼠标X轴输入,并限制在目标旋转的±xRotationLimit范围内
    float mouseX = Input.GetAxis(xAxis) * sensitivity;
    Quaternion mouseDeltaRot = Quaternion.AngleAxis(mouseX, Vector3.up);
    Quaternion tempRot = targetHorizontalRotation * mouseDeltaRot;

    // 检查旋转角度是否超出限制,超出则截断到最大允许值
    float angleDiff = Quaternion.Angle(targetHorizontalRotation, tempRot);
    if (angleDiff > xRotationLimit)
    {
        tempRot = Quaternion.RotateTowards(targetHorizontalRotation, tempRot, xRotationLimit);
    }

    // 应用最终旋转到玩家对象
    player.transform.localRotation = tempRot;
}

补充触发器进入时的初始化逻辑(避免首次进入的突兀跳转):

private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("CubeTrigger")) // 替换为你的触发器标签
    {
        trigger.clampRotation = true;
        // 初始化目标旋转为玩家当前的水平姿态
        Vector3 currentEuler = player.transform.localEulerAngles;
        targetHorizontalRotation = Quaternion.Euler(0, currentEuler.y, 0);
    }
}

关键修改说明

  • 修正RotateTowards参数顺序,用targetHorizontalRotation作为当前旋转状态,实现平滑向CubeObj转向的效果。
  • 分离垂直/水平轴逻辑,垂直轴保持原有限制,水平轴先处理自动转向,再叠加鼠标的有限调整。
  • 通过Quaternion.Angle计算鼠标调整后的旋转与目标旋转的夹角,确保X轴旋转范围不超过设定的xRotationLimit。
  • 触发器进入时初始化目标旋转,避免首次触发时的姿态突变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:22:23