Unity自定义重力切换时玩家对象绕前向轴异常旋转问题求解
问题定位
你的代码存在3个核心错误,直接导致离开触发区时出现异常旋转:
1. 朝向更新逻辑的up轴硬编码为世界Y轴
Turning方法中调用transform.LookAt时,第二个参数固定传入了世界坐标下的Vector3(0, 1, 0)作为up参考轴,但你的重力方向是动态变化的,up轴应该和当前重力方向相反(也就是-down),当重力方向从(0,-1,0)切换到(1,0,0)时,你依然用世界Y轴当up参考,就会导致物体绕前向轴翻转。
修复代码:
transform.LookAt(transform.position + lookDirection, -this.down);
2. 离开触发区时速度旋转角度计算错误
你在OnTriggerStay里是计算originalDown到newDown的相对夹角来旋转速度,但到了OnTriggerExit里直接用了绝对角度newAngle(相对于(1,0,0)的角度)来旋转速度,相当于多转了几倍的角度,导致速度方向和朝向完全不匹配,附带异常旋转。
修复逻辑:和Stay逻辑一致,先获取退出前的原重力方向,再计算原重力到目标限值重力的相对角度来旋转速度。
3. 触发区退出时角度判断用了无符号角度
你原来用Vector3.Angle计算的是0-180度的无符号角度,当实际角度为负的时候会判断错误,无法正确匹配最近的限值,需要改成Vector3.SignedAngle。
完整修复后的OnTriggerExit代码
void OnTriggerExit() { Vector3 originalDown = tControl.Down; // 先获取退出前的重力方向 Vector3 exitDir = tTransform.position - gameObject.transform.position; // 改用带符号的角度计算,避免负角度判断错误 float angle = Vector3.SignedAngle(exitDir, new Vector3(1, 0, 0), new Vector3(0, 0, 1)); Vector3 newDown; float deltaAngle; if (Mathf.Abs(angle - MinLimit) < Mathf.Abs(angle - MaxLimit)) { newDown = Quaternion.AngleAxis(MinLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0); deltaAngle = Vector3.SignedAngle(originalDown, newDown, new Vector3(0, 0, 1)); } else { newDown = Quaternion.AngleAxis(MaxLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0); deltaAngle = Vector3.SignedAngle(originalDown, newDown, new Vector3(0, 0, 1)); } Debug.Log("Exit: " + newDown + " " + deltaAngle); tControl.SetDirections(newDown); tRigidbody.velocity = Quaternion.AngleAxis(deltaAngle, new Vector3(0, 0, 1)) * tRigidbody.velocity; }
额外校验项
确认玩家Rigidbody组件已经勾选Freeze Rotation Z,避免物理模拟额外产生绕Z轴的旋转。
内容的提问来源于stack exchange,提问作者Zoltán Király
相关产品推荐
相关产品推荐

