使用Rigidbody MovePosition时3D敌人模型离地漂移问题求助
敌人离地漂移问题解决思路
核心问题分析
使用Rigidbody.MovePosition时直接修改位置会干扰重力的作用,加上受击时的外力影响,容易导致敌人Y轴位置偏离地面。另外部分状态代码存在方向未归一化的问题,会间接加剧移动异常。
具体修复方案
1. 统一约束移动时的Y轴位置
在所有调用MovePosition的状态中,固定Y轴到地面基准高度:
先在敌人初始化时记录地面高度(平面地形适用):
private float groundY; private Rigidbody rb; private CapsuleCollider collider; void Start() { rb = GetComponent<Rigidbody>(); collider = GetComponent<CapsuleCollider>(); // 记录初始地面高度,加上Collider半高防止陷入地面 groundY = rb.position.y; }巡逻状态修改:
Vector3 direction = (destination - rb.transform.position); float distance = Vector3.Distance(rb.transform.position, destination); direction.y = 0; // 计算目标位置后固定Y轴 Vector3 targetPos = enemy.transform.position + direction.normalized * speed * Time.deltaTime; targetPos.y = groundY; rb.MovePosition(targetPos); rb.transform.rotation = Quaternion.Slerp(rb.transform.rotation, Quaternion.LookRotation(direction), Time.deltaTime * rotationSpeed);追击状态修改(同时修复方向未归一化导致的速度异常):
direction2Player = player.position - enemy.transform.position; direction2Player.y = 0; // 归一化方向,确保移动速度稳定 Vector3 targetPos = rb.transform.position + runningSpeed * Time.deltaTime * direction2Player.normalized; targetPos.y = groundY; rb.MovePosition(targetPos); rb.transform.rotation = Quaternion.Slerp(rb.transform.rotation, Quaternion.LookRotation(direction2Player), Time.deltaTime * rotationSpeed);
2. 实时修正Y轴漂移
在FixedUpdate中持续检查并修正Y轴位置(物理帧同步,避免抖动):
private void FixedUpdate() { // 允许微小误差范围,防止频繁修正导致抖动 if (Mathf.Abs(rb.position.y - groundY) > 0.05f) { Vector3 fixedPos = rb.position; fixedPos.y = groundY; rb.MovePosition(fixedPos); } }
3. 优化Rigidbody设置
- 将Rigidbody的Collision Detection设为
Continuous Dynamic,避免快速移动时地形检测失效; - 确保敌人的Collider(推荐CapsuleCollider)尺寸合适,与地形碰撞体有正确的交互;
- 若不需要敌人在Y轴有物理移动,可勾选Rigidbody的Constraints →
Freeze Position Y(但会屏蔽重力,需根据需求选择)。
4. 替换攻击状态的临时修复
移除攻击状态中固定Y值的代码,改用全局的groundY或射线检测动态获取地面高度(适配非绝对平面地形):
public override void Update() { direction2Player = player.position - enemy.transform.position; direction2Player.y = 0; rb.transform.rotation = Quaternion.Slerp(rb.transform.rotation, Quaternion.LookRotation(direction2Player), Time.deltaTime * rotationSpeed); // 移除原固定Y值的代码,改用FixedUpdate中的统一修正 }
内容的提问来源于stack exchange,提问作者Annette G
相关产品推荐
相关产品推荐

