You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D技术问询:攻击状态下如何让NavMesh Agent停止移动但保持朝向玩家旋转

解决NavMesh僵尸攻击状态下停止移动但保持朝向玩家旋转的问题

这个问题我之前做生存类游戏的时候也碰到过——直接改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 18:52:35