Unity3D技术问询:攻击状态下如何让NavMesh Agent停止移动但保持朝向玩家旋转
这个问题我之前做生存类游戏的时候也碰到过——直接改speed为0确实会让Agent连自动旋转都停掉,因为NavMesh Agent的移动和自动旋转是绑定在一起的。下面给你两个靠谱的解决方案,都是我实际项目里用过的:
方案一:停止Agent移动+手动控制旋转(推荐)
核心思路是暂停Agent的路径跟随,但禁用它的自动旋转,然后自己写代码让僵尸平滑朝向玩家。这样既能保证僵尸不动,又能让它一直盯着玩家,而且不会破坏NavMesh的碰撞检测(比如不会穿墙)。
代码示例(Unity C#)
using UnityEngine; using UnityEngine.AI; public class ZombieController : MonoBehaviour { public Transform player; public NavMeshAgent navMeshAgent; public float attackRange = 2f; public float rotationSpeed = 5f; private bool isAttacking = false; void Update() { float distanceToPlayer = Vector3.Distance(transform.position, player.position); if (!isAttacking && distanceToPlayer <= attackRange) { // 进入攻击状态 EnterAttackState(); } else if (isAttacking && distanceToPlayer > attackRange) { // 退出攻击状态,恢复跟随 ExitAttackState(); } // 攻击状态下处理旋转 if (isAttacking) { RotateTowardsPlayer(); } else { // 非攻击状态下保持跟随 navMeshAgent.destination = player.position; } } void EnterAttackState() { isAttacking = true; // 停止Agent的移动(暂停路径跟随) navMeshAgent.isStopped = true; // 禁用Agent的自动旋转,交给我们手动控制 navMeshAgent.updateRotation = false; // 这里可以加上攻击动画的播放逻辑 // animator.SetTrigger("Attack"); } void ExitAttackState() { isAttacking = false; // 恢复Agent的移动和自动旋转 navMeshAgent.isStopped = false; navMeshAgent.updateRotation = true; // 恢复移动动画 // animator.SetTrigger("Walk"); } void RotateTowardsPlayer() { // 计算从僵尸指向玩家的方向,忽略Y轴(防止抬头/低头) Vector3 targetDirection = player.position - transform.position; targetDirection.y = 0; // 转成目标旋转角度 Quaternion targetRotation = Quaternion.LookRotation(targetDirection); // 平滑过渡到目标旋转,避免突然转头 transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } }
为什么这个方法有效?
navMeshAgent.isStopped = true:会让Agent立刻停止移动,并且暂停路径的更新,节省性能,同时保留Agent的碰撞检测(比如不会穿过场景障碍物)。navMeshAgent.updateRotation = false:关闭Agent的自动旋转逻辑,这样我们就能完全控制僵尸的朝向,不会被Agent的自动行为干扰。- 手动用
Quaternion.Lerp实现平滑旋转:让僵尸转头的动作更自然,不会显得僵硬。
方案二:设置Agent速度为0+强制旋转(适合简单场景)
如果你的场景比较简单,不需要保留Agent的路径状态,也可以用这个更直接的方法:
void EnterAttackState() { isAttacking = true; // 直接把速度设为0,停止移动 navMeshAgent.speed = 0; // 禁用自动旋转 navMeshAgent.updateRotation = false; }
然后同样在Update里调用上面的RotateTowardsPlayer方法控制朝向。不过这个方法的缺点是,Agent仍然会继续计算路径(只是不移动),会浪费一点性能,所以更推荐方案一。
额外注意点
- 如果你的僵尸有动画状态机,记得在进入/退出攻击状态时切换对应的动画(比如攻击动画/行走动画),让整个逻辑更完整。
- 可以根据需求调整
rotationSpeed的值,数值越大转头越快,越小越平滑。 - 如果是3D游戏需要上下旋转(比如僵尸抬头看空中的玩家),可以去掉
targetDirection.y = 0这一行。
内容的提问来源于stack exchange,提问作者Nassim Hamza
相关产品推荐
相关产品推荐

