# Unity NavMeshAgent 核心原理

## 一句话结论

Unity NavMesh 的核心是 **先把可行走区域烘焙或构建成导航网格，再在网格上规划路径，并用 NavMeshAgent 做沿路径移动和局部避让**。它更像“路径导航系统”，局部避障只是其中一部分。

在 FishROV benchmark 中，`UnityNavMeshAdapter` 会运行时构建一张平面 NavMesh，然后给 agent 添加 `NavMeshAgent` 作为对照组。

## NavMesh 解决的问题

RVO2 主要解决动态体之间的局部避障，但它不理解复杂地图。

NavMesh 重点解决的是：

```text
哪里能走？
从当前位置到目标点，应该沿哪些可行区域走？
遇到墙、洞、不可通行区域时，怎么绕过去？
```

所以 NavMesh 更偏全局可达性和路径规划。

## 导航网格

NavMesh 会把场景中的可行走区域转换成多边形网格。

可以理解为：

```text
原始场景几何
  -> 提取可走区域
  -> 合并成多边形网格
  -> agent 在网格上找路径
```

在普通地面游戏里，这非常适合角色在地形、房间、走廊之间移动。

## 路径规划

NavMeshAgent 的目标通常不是“直接向目标点走”，而是：

1. 找到自己所在的 NavMesh 多边形。
2. 找到目标所在的 NavMesh 多边形。
3. 在多边形图上搜索路径。
4. 得到一串路径拐点。
5. 沿着路径拐点移动。

这部分通常接近 A* 图搜索思想，只是图节点不是格子，而是 NavMesh 多边形或多边形边界。

## 局部避障

NavMeshAgent 除了路径跟随，还会做一定局部避障：

- 根据 agent 半径避免互相穿透。
- 根据 `avoidancePriority` 决定谁更应该让路。
- 根据 `obstacleAvoidanceType` 决定避障质量和开销。
- 根据速度、加速度、角速度调整移动。

但要注意：NavMeshAgent 的局部避障不是完整的 ORCA/RVO2 替代品。它主要服务于“角色沿 NavMesh 路径移动”的工程场景。

## 每帧流程

典型 NavMeshAgent 流程是：

1. agent 位于 NavMesh 上。
2. 设置目标点或期望移动。
3. NavMeshAgent 更新路径跟随和局部避障。
4. 输出新位置或速度。
5. Unity 自动或外部代码同步 Transform。

当前 benchmark 为了公平比较，没有让 NavMeshAgent 独占 Transform，而是：

- 让 NavMeshAgent 计算避障速度。
- 把速度交给 `BenchmarkAgent.ApplyVelocity`。
- 再由统一的 `BenchmarkAgent.Integrate` 推进 Transform。

这能保持各方案共用同一套移动入口，但也会带来适配层同步问题。

## 为什么可能抖动

NavMeshAgent 在 benchmark 中抖动更明显，通常有几个原因：

- NavMeshAgent 自己有内部位置 `nextPosition`，可视 Transform 又由 benchmark 积分推进，二者需要同步。
- 高密度场景中 agent 互相挤压，NavMeshAgent 会频繁修正速度。
- 如果目标方向和避障方向来回冲突，就会出现左右摆动。
- NavMesh 是平面系统，2.5D 或 3D 表现会被压回平面理解。
- 当前场景是压力测试，不是典型 NavMesh 地图导航场景。

当前代码已经对 NavMeshAgent 输出速度做了按 `acceleration` 的平滑，减少单帧速度尖峰，但它仍可能比 RVO2 更容易抖。

## 关键参数

- `radius`：agent 在 NavMesh 上的占位半径。
- `height`：agent 高度。
- `speed`：最大速度。
- `acceleration`：速度变化上限。
- `angularSpeed`：转向速度。
- `avoidancePriority`：局部避让优先级。
- `obstacleAvoidanceType`：避障质量。
- `autoBraking`：到达目标前是否自动减速。

在高密度鱼群测试里，最敏感的通常是：

- `radius`
- `acceleration`
- `avoidancePriority`
- `obstacleAvoidanceType`

## 优点

- 工程成熟，Unity 内置。
- 对静态地图、走廊、房间、地形导航很实用。
- 能处理全局可达性，不只是局部避障。
- 有现成 Editor/Runtime API。
- 适合作为游戏角色导航的基础对照。

## 局限

- 主要是平面导航系统，不适合完整 3D 水下体积避障。
- 局部避障不是它最强的部分。
- 高密度动态 agent 容易抖动或互相挤压。
- 对纯动态鱼群避障，可能不如专门的 RVO/ORCA 方法自然。
- 如果只是空旷平面上的多 agent 避障，NavMesh 的全局路径能力发挥不出来。

## 在 FishROV 中的观察重点

测试 NavMesh 时重点看：

- `XZ重叠对` 是否比 RVO2 高。
- 抖动是否主要发生在高密度对向穿流、圆阵高压场景。
- `模拟耗时` 是否稳定。
- 速度平滑后是否减少视觉抖动，但仍保持避障响应。
- 2.5D/3D 模式下是否只是平面避障导致视觉穿插。

## 对自研算法的启发

NavMesh 的价值不在于局部避障算法本身，而在于“全局可达性层”：

```text
全局层：告诉 agent 应该往哪里走，避开不可通行区域。
局部层：在当前速度附近躲开动态邻居。
```

后续更好的 FishROV 避障系统可以考虑分层：

- 全局目标/航线：NavMesh、路径图、流场、A*。
- 局部动态避障：RVO2、采样速度、势场、学习策略。
- 运动表现层：速度平滑、朝向约束、最大加速度。

这样能避免把所有问题都塞进一个局部避障算法里。
