Game_Num_Basics_And_Calc

🧭 NavMesh 寻路与状态控制指南 (NavMesh Pathfinding & CC Interaction)

本文档详细阐述 Project Vampirefall 中敌人如何利用 Unity NavMesh 系统进行寻路,重点解析异常状态 (CC) 下的寻路控制,以及动态阻挡 (塔防) 的实现细节。


1. 核心组件架构 (Core Components)

在 Unity 中,寻路不仅仅是 SetDestination。对于复杂的 ARPG + TD 游戏,我们需要精细控制 NavMeshAgent

1.1 Agent 配置的最佳实践


2. 状态控制与寻路交互 (CC & Pathfinding)

这是 ARPG 开发中最容易出 Bug 的地方:如何让 NavMeshAgent 正确响应“冰冻”、“击退”等物理效果?

❄️ 2.1 减速 (Slow)

🧊 2.2 定身/冰冻 (Root / Freeze)

💫 2.3 眩晕 (Stun)

🥊 2.4 击退 (Knockback) —— 最难点

NavMeshAgentRigidbody 是死对头。Agent 试图吸附在地面,Rigidbody 试图飞出去。


3. 实用案例大全 (Practical Use Cases)

⚔️ Case A: 到达攻击距离 (Reaching Attack Range)

当怪物进入射程时,如何优雅地停下来攻击,而不是推着玩家走?

体积修正 (Size Adjustment)

在塔防中,塔通常有很大的碰撞体积(如 Radius = 2.0m),而小怪只有 Radius = 0.5m。直接计算 Vector3.Distance (中心点距离) 会导致小怪贴着塔站,或者打不到塔。

🧱 Case B: 动态阻挡与堵路检测 (Dynamic Blocking)

在塔防模式下,玩家放塔不能把怪物的路彻底堵死 (Maze Blocking Rule)。

让怪物像蜘蛛一样翻越城墙,或者跳过沟壑。

🎭 Case D: 游击/风筝 (Kiting)

弓箭手不仅要追玩家,还要保持距离。

🐜 Case E: 拥挤处理 (Crowd Separation)

几百个僵尸挤在一起,互相推挤导致卡顿。


4. 代码片段:安全的击退处理

public class NavMeshMovement : MonoBehaviour
{
    [SerializeField] private NavMeshAgent _agent;
    [SerializeField] private Rigidbody _rb;

    // 协程:处理击退
    public IEnumerator ApplyKnockback(Vector3 force, float duration)
    {
        // 1. 切断 NavMesh 连接
        _agent.isStopped = true; // 先停逻辑
        _agent.enabled = false;  // 再关组件 (重要顺序)
        _rb.isKinematic = false; // 开启物理

        // 2. 施加力
        _rb.AddForce(force, ForceMode.Impulse);

        // 3. 等待物理模拟
        yield return new WaitForSeconds(duration);

        // 4. 恢复 NavMesh
        _rb.velocity = Vector3.zero;
        _rb.isKinematic = true;
        
        // 寻找最近的有效地面,防止卡在墙里
        if (NavMesh.SamplePosition(transform.position, out NavMeshHit hit, 2.0f, NavMesh.AllAreas))
        {
            _agent.Warp(hit.position); // 瞬移回网格
            _agent.enabled = true;
            _agent.isStopped = false;
        }
        else
        {
            // 异常处理:被击飞出地图了,直接处死
            GetComponent<Health>().Kill(); 
        }
    }
}

5. 常见坑点速查 (Troubleshooting)

现象 原因 解决方案
怪物原地转圈 目标点在脚下,但因为 StoppingDistance 没停住。 增大 StoppingDistance 或检测 agent.remainingDistance < Threshold 手动 Stop。
怪物穿墙 速度太快,或 NavMeshObstacle 没有开 Carve 开启 Carve;对于极快单位,改用 Raycast 检测前方障碍。
浮空/陷入地下 Agent 的 BaseOffset 设置不对,或模型原点不在脚底。 调整 BaseOffset;确保美术模型的 Pivot 在脚底中心。
性能暴跌 每一帧都对 100 个怪调用 SetDestination 必须限制频率!使用协程每 0.2s 更新一次路径,或仅当目标移动超过 1米时更新。