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

Unity C#中如何限制3D场景内门的四元数旋转角度?

《恐鬼症》风格门的旋转角度限制实现

我正在制作《恐鬼症(Phasmophobia)》风格的可交互门,支持点击拖拽把手开关门。目前已实现让门轴朝向另一端的可抓取目标完成开门动作,目标也会自动重置到门的合理位置。现在需要实现门旋转到设定角度范围后停止跟随目标,避免出现异常旋转的情况——当前使用Quaternion.LookRotation实现旋转,不知道如何用欧拉角变量限制旋转范围,相关C#代码如下:

// 原代码片段
private void Update()
{
   DoorVector = transform.position;
    TargetVector = DoorTarget.transform.position;

    DoorX = DoorVector.x;
    DoorZ = DoorVector.z;

    TargetX = TargetVector.x;
    TargetZ = TargetVector.z;
    

    DoorRotation = Quaternion.LookRotation(new Vector3(TargetX, 0, TargetZ) - new Vector3(DoorX, 0, DoorZ));

    // 伪代码: if(MaxAngle<eulerAngle<Min Angle) {执行下面的代码}
    
    spd = Mathf.Min (DoorSpeed * Time.deltaTime);
   transform.rotation = Quaternion.Lerp (transform.rotation , DoorRotation, spd);
}

解决方案:基于欧拉角限制旋转范围

核心思路是:先计算目标旋转对应的欧拉角,将其限制在设定的范围内,再将限制后的欧拉角转回四元数应用到门上。

步骤1:定义角度限制变量

在脚本顶部添加以下公共变量,方便在Inspector面板中调整:

public float minDoorAngle = 0f; // 门关闭时的基准角度
public float maxDoorAngle = 90f; // 门完全打开的最大角度
private Vector3 initialEuler; // 门的初始欧拉角,用于计算相对旋转

步骤2:初始化初始角度

在Start方法中记录门的初始旋转角度:

void Start()
{
    initialEuler = transform.eulerAngles;
}

步骤3:修改Update方法的旋转逻辑

替换原有的Update代码,加入角度限制逻辑:

private void Update()
{
    // 计算门与目标的方向向量(只保留XZ平面)
    Vector3 direction = DoorTarget.transform.position - transform.position;
    direction.y = 0; // 忽略Y轴,保证门只在水平方向旋转

    // 生成目标旋转四元数
    Quaternion targetRotation = Quaternion.LookRotation(direction);

    // 将目标旋转转为欧拉角,提取Y轴旋转(门的旋转轴通常是Y轴)
    float targetYAngle = targetRotation.eulerAngles.y;

    // 计算相对于初始角度的旋转偏移,处理角度循环(0-360)问题
    float relativeYAngle = Mathf.DeltaAngle(initialEuler.y, targetYAngle);

    // 将旋转角度限制在设定的范围内
    float clampedAngle = Mathf.Clamp(relativeYAngle, minDoorAngle, maxDoorAngle);

    // 生成限制后的最终旋转四元数
    Quaternion clampedRotation = Quaternion.Euler(initialEuler.x, initialEuler.y + clampedAngle, initialEuler.z);

    // 平滑插值应用旋转
    float spd = DoorSpeed * Time.deltaTime;
    transform.rotation = Quaternion.Lerp(transform.rotation, clampedRotation, spd);
}

关键细节说明

  • 使用Mathf.DeltaAngle处理角度的360度循环问题,避免从350度跳到10度时出现异常旋转。
  • 假设门是绕Y轴旋转(大部分场景下的门都是如此),如果你的门旋转轴是其他轴,只需替换对应的欧拉角分量(比如X或Z)。
  • Mathf.Clamp直接将相对旋转角度限制在minDoorAngle和maxDoorAngle之间,超过范围时会被截断,门就不会继续旋转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 00:33:10