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
相关产品推荐
相关产品推荐

