Unity 3D:简易胶囊角色自稳定器开发问题求助
胶囊角色不倒翁自扶正解决方案
现有代码问题分析
- 第一段代码:仅处理Z轴旋转,未覆盖胶囊倾斜的主要方向(X轴);在
OnCollisionStay中持续施加扭矩易引发过冲翻滚;未结合物理帧时间增量计算扭矩,力的控制不稳定。 - 第二段代码:错误将扭矩施加到Y轴(Y轴为角色转向轴,不应参与扶正逻辑);
Quaternion.Angle返回无方向的正角度,用Mathf.Sign(angle)无法正确判断旋转方向,导致扶正力方向完全错误。
有效实现代码
使用FixedUpdate处理物理逻辑,通过计算当前旋转与目标直立旋转的差值施加扭矩,同时加入角速度阻尼避免过冲:
using UnityEngine; public class SelfRighting : MonoBehaviour { [SerializeField] private Rigidbody _rb; [SerializeField] private float _rightingTorque = 20f; [SerializeField] private float _maxAngle = 60f; [SerializeField] private float _angularDamping = 0.5f; private void FixedUpdate() { if (IsGrounded()) { // 目标旋转:保留当前Y轴转向,X、Z轴回正 Quaternion targetRot = Quaternion.Euler(0f, transform.rotation.eulerAngles.y, 0f); // 计算当前旋转与目标旋转的差值 Quaternion deltaRot = targetRot * Quaternion.Inverse(transform.rotation); Vector3 deltaEuler = deltaRot.eulerAngles; // 修正欧拉角360度循环问题,转换为-180~180范围 deltaEuler.x = Mathf.DeltaAngle(0f, deltaEuler.x); deltaEuler.z = Mathf.DeltaAngle(0f, deltaEuler.z); // 限制最大倾斜角度,避免过度施力 float clampedX = Mathf.Clamp(deltaEuler.x, -_maxAngle, _maxAngle); float clampedZ = Mathf.Clamp(deltaEuler.z, -_maxAngle, _maxAngle); // 计算与倾斜角度成正比的扶正扭矩 Vector3 torque = new Vector3(clampedX, 0f, clampedZ) * _rightingTorque * Time.fixedDeltaTime; torque = transform.TransformDirection(torque); _rb.AddTorque(torque); // 角速度阻尼,减少过冲摇晃 Vector3 angularVelocity = _rb.angularVelocity; angularVelocity.x *= (1 - _angularDamping * Time.fixedDeltaTime); angularVelocity.z *= (1 - _angularDamping * Time.fixedDeltaTime); _rb.angularVelocity = angularVelocity; } } // 射线检测判断是否接触地面(可根据场景调整) private bool IsGrounded() { float rayLength = 0.1f; Vector3 rayStart = transform.position - new Vector3(0f, transform.localScale.y / 2f, 0f); return Physics.Raycast(rayStart, Vector3.down, rayLength, LayerMask.GetMask("Ground")); } }
使用说明
- 将脚本挂载到胶囊角色上,拖入对应Rigidbody组件。
- 调整参数适配场景:
_rightingTorque:扶正力度,数值越大扶正速度越快。_maxAngle:最大倾斜角度限制,超出后不再施加额外力度。_angularDamping:角速度阻尼,数值越大越不容易出现过冲摇晃。
- 确保地面Layer设置为
Ground,或修改IsGrounded中的LayerMask匹配你的场景配置。
关键改进点
- 用
FixedUpdate处理物理逻辑:贴合Unity物理更新时机,避免力的帧间不稳定。 - 精准计算倾斜方向:正确识别X、Z轴的倾斜角度,确保扭矩方向始终指向直立状态。
- 加入角速度阻尼:解决过冲翻滚问题,实现平滑的扶正效果。
- 射线检测替代
OnCollisionStay:避免持续触发导致的力叠加异常。
内容的提问来源于stack exchange,提问作者desl8
相关产品推荐
相关产品推荐

