Document avoidance algorithm principles
This commit is contained in:
148
FishROV/Docs/rvo2-core-principles.md
Normal file
148
FishROV/Docs/rvo2-core-principles.md
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# RVO2 / ORCA 核心原理
|
||||||
|
|
||||||
|
## 一句话结论
|
||||||
|
|
||||||
|
RVO2 的核心是 **在速度空间里选择一个尽量接近期望速度、同时在未来一段时间内不会和邻居相撞的速度**。它不是先规划一条全局路径,而是每帧根据周围动态体的位置、速度、半径,实时修正当前速度。
|
||||||
|
|
||||||
|
在 FishROV benchmark 中,`Rvo2Adapter` 直接调用 `RVO.Simulator`,把 Unity 的 `x/z` 平面映射到 RVO2 的 `x/y` 平面。
|
||||||
|
|
||||||
|
## 要解决的问题
|
||||||
|
|
||||||
|
普通 steering 常见做法是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
朝目标走
|
||||||
|
遇到近邻就加一个远离力
|
||||||
|
最后合成速度
|
||||||
|
```
|
||||||
|
|
||||||
|
这种方法容易出现几个问题:
|
||||||
|
|
||||||
|
- 只看当前距离,不看未来是否会碰撞。
|
||||||
|
- 多个 agent 同时互相躲避时,可能左右摇摆。
|
||||||
|
- 高密度时排斥力叠加会让速度很乱。
|
||||||
|
- 很难证明“这个速度在未来一小段时间内安全”。
|
||||||
|
|
||||||
|
RVO2/ORCA 换了一个视角:不直接在位置空间里推开物体,而是在速度空间里判断哪些速度会导致未来碰撞。
|
||||||
|
|
||||||
|
## Velocity Obstacle
|
||||||
|
|
||||||
|
假设有两个 agent:A 和 B。
|
||||||
|
|
||||||
|
- A 的位置是 `pA`,速度是 `vA`,半径是 `rA`。
|
||||||
|
- B 的位置是 `pB`,速度是 `vB`,半径是 `rB`。
|
||||||
|
- 如果未来某个时间内,两者中心距离小于 `rA + rB`,就会碰撞。
|
||||||
|
|
||||||
|
Velocity Obstacle 的意思是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
对 A 来说,有一片速度区域是危险的。
|
||||||
|
如果 A 选择这片区域内的速度,
|
||||||
|
在假设 B 继续按当前速度运动的情况下,
|
||||||
|
A 会在未来撞到 B。
|
||||||
|
```
|
||||||
|
|
||||||
|
这片危险区域通常可以理解成速度空间中的一个锥形区域。
|
||||||
|
|
||||||
|
## RVO:双方共同承担避让
|
||||||
|
|
||||||
|
普通 VO 假设“我来躲别人”。如果所有 agent 都这样算,容易过度避让。
|
||||||
|
|
||||||
|
RVO 的思路是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
A 和 B 都是主动体。
|
||||||
|
发生潜在碰撞时,不应该让 A 单独承担全部避让。
|
||||||
|
双方各承担一部分速度修正。
|
||||||
|
```
|
||||||
|
|
||||||
|
这让多 agent 场景更自然,尤其适合鱼群、机器人群、行人群这类对等个体。
|
||||||
|
|
||||||
|
## ORCA:把避障变成线性约束
|
||||||
|
|
||||||
|
ORCA 是 RVO 的改进形式。它会为每个邻居构造一个半平面约束:
|
||||||
|
|
||||||
|
```text
|
||||||
|
为了避免和这个邻居碰撞,
|
||||||
|
当前 agent 的新速度必须落在这条线的一侧。
|
||||||
|
```
|
||||||
|
|
||||||
|
多个邻居会产生多个约束。最终问题变成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
在所有安全半平面约束内,
|
||||||
|
找一个距离期望速度最近的速度。
|
||||||
|
```
|
||||||
|
|
||||||
|
这就是 RVO2 高效的关键:每帧不是做复杂全局搜索,而是在低维速度空间里做局部约束求解。
|
||||||
|
|
||||||
|
## 每帧流程
|
||||||
|
|
||||||
|
RVO2 的典型帧流程是:
|
||||||
|
|
||||||
|
1. 更新每个 agent 的当前位置。
|
||||||
|
2. 给每个 agent 设置期望速度。
|
||||||
|
3. 使用空间结构查找邻居。
|
||||||
|
4. 为每个邻居构造 ORCA 约束。
|
||||||
|
5. 求出新的安全速度。
|
||||||
|
6. 用新速度推进 agent。
|
||||||
|
|
||||||
|
在当前 benchmark 中,推进 Transform 由统一的 `BenchmarkAgent.Integrate` 负责,RVO2 adapter 只负责把期望速度改成避障后的速度。
|
||||||
|
|
||||||
|
## 关键参数
|
||||||
|
|
||||||
|
- `radius`:agent 半径,直接决定碰撞距离。
|
||||||
|
- `neighborDist`:考虑多远范围内的邻居。
|
||||||
|
- `maxNeighbors`:最多考虑多少邻居。
|
||||||
|
- `timeHorizon`:预测未来多久内的碰撞。
|
||||||
|
- `maxSpeed`:最大速度。
|
||||||
|
- `timeStep`:仿真步长。
|
||||||
|
|
||||||
|
这些参数会明显影响表现:
|
||||||
|
|
||||||
|
- `neighborDist` 太小:反应太晚,容易碰撞。
|
||||||
|
- `neighborDist` 太大:邻居过多,性能下降,也可能过度保守。
|
||||||
|
- `timeHorizon` 太短:贴脸才躲。
|
||||||
|
- `timeHorizon` 太长:提前过度避让,可能绕不开或变慢。
|
||||||
|
- `maxNeighbors` 太低:高密度时会漏掉重要邻居。
|
||||||
|
|
||||||
|
## 优点
|
||||||
|
|
||||||
|
- 对多动态 agent 很合适。
|
||||||
|
- 速度空间建模清晰,可解释。
|
||||||
|
- 不需要全局路径。
|
||||||
|
- 高密度局部避障比简单排斥力稳定。
|
||||||
|
- 理论上比纯启发式 steering 更有安全约束感。
|
||||||
|
|
||||||
|
## 局限
|
||||||
|
|
||||||
|
- RVO2-CS 是 2D 算法,当前项目的 3D 模式会投影到 XZ 平面。
|
||||||
|
- 它不负责全局规划,遇到死胡同或复杂障碍仍可能局部最优。
|
||||||
|
- 只考虑局部未来,不能理解长远路线收益。
|
||||||
|
- 参数不合适时仍会碰撞、停滞或过度保守。
|
||||||
|
- 如果 benchmark 初始位置已经重叠,它需要时间把重叠解开。
|
||||||
|
|
||||||
|
## 在 FishROV 中的观察重点
|
||||||
|
|
||||||
|
测试 RVO2 时重点看:
|
||||||
|
|
||||||
|
- `XZ重叠对` 是否能稳定下降。
|
||||||
|
- `3D重叠对` 是否比 XZ 少,判断 2.5D 高度层是否只是视觉重叠。
|
||||||
|
- 高密度场景中 `模拟耗时` 是否随数量近似线性或亚二次增长。
|
||||||
|
- 是否出现互相卡住、绕圈或过早减速。
|
||||||
|
|
||||||
|
## 对自研算法的启发
|
||||||
|
|
||||||
|
RVO2 最值得吸收的不是具体代码,而是这个思想:
|
||||||
|
|
||||||
|
```text
|
||||||
|
不要只问“障碍在哪里”,
|
||||||
|
还要问“我现在可选的速度里,哪些会在未来导致碰撞”。
|
||||||
|
```
|
||||||
|
|
||||||
|
后续自研算法可以借鉴:
|
||||||
|
|
||||||
|
- 用预测碰撞时间代替单纯距离。
|
||||||
|
- 在速度空间做候选速度打分。
|
||||||
|
- 对不同邻居按风险程度加权。
|
||||||
|
- 把“接近期望速度”和“避碰安全”放到同一个优化目标里。
|
||||||
234
FishROV/Docs/sampling-local-avoidance-core-principles.md
Normal file
234
FishROV/Docs/sampling-local-avoidance-core-principles.md
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
# 采样避障学习版核心原理
|
||||||
|
|
||||||
|
## 一句话结论
|
||||||
|
|
||||||
|
采样避障学习版的核心是 **不直接求解析最优解,而是在一批候选速度中打分选择当前最合适的速度**。它是项目内自写的学习基线,目标是可读、可改、可调参,而不是证明无碰撞。
|
||||||
|
|
||||||
|
实现位置:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Assets/Scripts/Benchmark/FrameworkAdapters/SamplingLocalAvoidanceAdapter.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
## 为什么写这个版本
|
||||||
|
|
||||||
|
RVO2/ORCA 很成熟,但内部数学和约束求解不容易快速改。
|
||||||
|
|
||||||
|
NavMeshAgent 工程成熟,但它是完整导航系统,不是纯局部避障算法。
|
||||||
|
|
||||||
|
学习版采样避障的目的不同:
|
||||||
|
|
||||||
|
- 给你一个完全可控的 baseline。
|
||||||
|
- 让每个评分项都能看懂、能改权重。
|
||||||
|
- 方便测试“如果我改变风险函数,会发生什么”。
|
||||||
|
- 为后续写更好的自研算法提供实验平台。
|
||||||
|
|
||||||
|
## 基本思路
|
||||||
|
|
||||||
|
每帧对每个 agent 做三步:
|
||||||
|
|
||||||
|
```text
|
||||||
|
1. 找附近邻居
|
||||||
|
2. 生成候选速度
|
||||||
|
3. 给候选速度打分,选择分数最低的速度
|
||||||
|
```
|
||||||
|
|
||||||
|
它不是像 RVO2 那样构造半平面约束,而是把避障变成一个启发式评分问题。
|
||||||
|
|
||||||
|
## 空间哈希找邻居
|
||||||
|
|
||||||
|
如果每个 agent 都和所有其他 agent 比较,复杂度是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
O(n²)
|
||||||
|
```
|
||||||
|
|
||||||
|
5000 条鱼时会非常贵。
|
||||||
|
|
||||||
|
所以学习版先把 agent 放进空间哈希格子:
|
||||||
|
|
||||||
|
```text
|
||||||
|
世界坐标 x/z
|
||||||
|
-> 根据 cellSize 计算格子坐标
|
||||||
|
-> 每个格子保存一批 agent
|
||||||
|
-> 查询时只看自己附近几个格子
|
||||||
|
```
|
||||||
|
|
||||||
|
这样大多数情况下只需要检查附近 agent,而不是全量扫描。
|
||||||
|
|
||||||
|
## 候选速度
|
||||||
|
|
||||||
|
候选速度主要来自:
|
||||||
|
|
||||||
|
- 当前期望速度。
|
||||||
|
- 零速度。
|
||||||
|
- 以期望方向为基准旋转出的多个方向。
|
||||||
|
- 不同速度倍率,例如全速和半速。
|
||||||
|
|
||||||
|
可以理解为:
|
||||||
|
|
||||||
|
```text
|
||||||
|
我想往目标方向走,
|
||||||
|
但也试试稍微偏左、偏右、减速、停下,
|
||||||
|
看哪个风险最低。
|
||||||
|
```
|
||||||
|
|
||||||
|
当前版本每帧采样固定数量方向,优先保持实现简单和可读。
|
||||||
|
|
||||||
|
## 评分函数
|
||||||
|
|
||||||
|
每个候选速度都会计算一个分数:
|
||||||
|
|
||||||
|
```text
|
||||||
|
总分 =
|
||||||
|
目标偏差惩罚
|
||||||
|
+ 速度平滑惩罚
|
||||||
|
+ 预测碰撞惩罚
|
||||||
|
+ 当前重叠惩罚
|
||||||
|
+ 边界惩罚
|
||||||
|
```
|
||||||
|
|
||||||
|
分数越低,速度越适合当前帧。
|
||||||
|
|
||||||
|
## 目标偏差惩罚
|
||||||
|
|
||||||
|
agent 不能为了避障完全忘记目标。
|
||||||
|
|
||||||
|
如果候选速度和期望速度差得很远,就加惩罚:
|
||||||
|
|
||||||
|
```text
|
||||||
|
goalPenalty = |candidate - preferred|²
|
||||||
|
```
|
||||||
|
|
||||||
|
这个项越大,agent 越倾向继续朝目标走。
|
||||||
|
|
||||||
|
## 速度平滑惩罚
|
||||||
|
|
||||||
|
如果每帧都选一个差异很大的速度,视觉上会抖。
|
||||||
|
|
||||||
|
所以学习版会惩罚候选速度和上一帧速度的差异:
|
||||||
|
|
||||||
|
```text
|
||||||
|
smoothPenalty = |candidate - lastVelocity|²
|
||||||
|
```
|
||||||
|
|
||||||
|
这个项越大,运动越平滑,但反应也可能变慢。
|
||||||
|
|
||||||
|
## 当前重叠惩罚
|
||||||
|
|
||||||
|
如果两个 agent 当前已经重叠,必须强烈惩罚继续贴近的速度。
|
||||||
|
|
||||||
|
学习版会计算:
|
||||||
|
|
||||||
|
```text
|
||||||
|
当前距离 - 两者半径和
|
||||||
|
```
|
||||||
|
|
||||||
|
如果小于 0,说明已经重叠。重叠越深,惩罚越高。
|
||||||
|
|
||||||
|
这个项主要用来处理初始生成过密、或上一帧已经挤在一起的情况。
|
||||||
|
|
||||||
|
## 预测碰撞惩罚
|
||||||
|
|
||||||
|
只看当前距离不够。两个 agent 现在很远,但如果高速对冲,很快也会撞。
|
||||||
|
|
||||||
|
学习版会估算候选速度下的最近接近时刻:
|
||||||
|
|
||||||
|
```text
|
||||||
|
relativePosition = otherPosition - selfPosition
|
||||||
|
relativeVelocity = candidateVelocity - otherVelocity
|
||||||
|
closestTime = clamp(-dot(relativePosition, relativeVelocity) / |relativeVelocity|², 0, timeHorizon)
|
||||||
|
```
|
||||||
|
|
||||||
|
然后计算在 `closestTime` 时两者距离是否小于安全半径。
|
||||||
|
|
||||||
|
如果预测未来会撞,就加惩罚;越快撞、越深撞,惩罚越高。
|
||||||
|
|
||||||
|
这一步是学习版最接近 RVO 思想的地方:它不只问“现在近不近”,而是问“这个速度会不会导致未来碰撞”。
|
||||||
|
|
||||||
|
## 边界惩罚
|
||||||
|
|
||||||
|
benchmark 有 arena 半径。候选速度如果把 agent 推向边界外,就加惩罚。
|
||||||
|
|
||||||
|
这能减少 agent 因避障一路逃出场地边缘,然后被 `BenchmarkAgent.Integrate` 夹回边界导致的异常运动。
|
||||||
|
|
||||||
|
## 每帧流程
|
||||||
|
|
||||||
|
学习版每帧流程是:
|
||||||
|
|
||||||
|
1. adapter 收集每个 agent 的期望速度。
|
||||||
|
2. 构建空间哈希。
|
||||||
|
3. 对每个 agent 生成候选速度。
|
||||||
|
4. 对候选速度逐个打分。
|
||||||
|
5. 选择最低分速度。
|
||||||
|
6. 写回 `BenchmarkAgent.ApplyVelocity`。
|
||||||
|
7. benchmark 统一积分移动。
|
||||||
|
|
||||||
|
## 优点
|
||||||
|
|
||||||
|
- 完全自写,许可证清晰。
|
||||||
|
- 很容易读懂和调参。
|
||||||
|
- 可以快速增加新的评分项。
|
||||||
|
- 可以观察每个启发式对结果的影响。
|
||||||
|
- 适合作为自研算法实验起点。
|
||||||
|
|
||||||
|
## 局限
|
||||||
|
|
||||||
|
- 不保证无碰撞。
|
||||||
|
- 候选速度数量有限,可能错过真正好速度。
|
||||||
|
- 权重依赖场景,换场景可能需要重新调。
|
||||||
|
- 高密度时仍可能局部最优或互相卡住。
|
||||||
|
- 当前实现是 CPU 主线程版本,还没有 Job/Burst 优化。
|
||||||
|
- 它是启发式算法,不是完整 ORCA。
|
||||||
|
|
||||||
|
## 和 RVO2 的区别
|
||||||
|
|
||||||
|
| 维度 | RVO2 / ORCA | 采样避障学习版 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 核心方法 | 速度空间半平面约束求解 | 候选速度打分 |
|
||||||
|
| 理论性 | 更强 | 较弱 |
|
||||||
|
| 可解释性 | 数学清晰,但实现复杂 | 每个评分项直接可读 |
|
||||||
|
| 可调性 | 参数较少但影响大 | 权重和候选集都可改 |
|
||||||
|
| 无碰撞保证 | 更接近可证明安全 | 不保证 |
|
||||||
|
| 学习价值 | 学习速度障碍理论 | 学习工程化评分和调参 |
|
||||||
|
|
||||||
|
## 和 NavMesh 的区别
|
||||||
|
|
||||||
|
| 维度 | Unity NavMeshAgent | 采样避障学习版 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 主要目标 | 地图导航和路径跟随 | 局部动态避障 |
|
||||||
|
| 地图理解 | 有 NavMesh 可达性 | 没有地图理解 |
|
||||||
|
| 动态群体 | 可做但不是最专门 | 专门面向局部邻居 |
|
||||||
|
| 3D 体积 | 主要平面 | 当前也主要平面,可扩展 |
|
||||||
|
| 可改性 | 内部黑盒较多 | 完全可改 |
|
||||||
|
|
||||||
|
## 后续改进方向
|
||||||
|
|
||||||
|
这个学习版后续可以逐步升级:
|
||||||
|
|
||||||
|
- 增加候选速度自适应采样,而不是固定 16 方向。
|
||||||
|
- 把邻居风险按距离、相对速度、角色类型加权。
|
||||||
|
- 引入最大加速度和最大转向角约束。
|
||||||
|
- 增加“右侧通行/左侧通行”偏置,减少对称死锁。
|
||||||
|
- 增加队形或鱼群凝聚项。
|
||||||
|
- 使用 Job System / Burst 优化空间哈希和评分。
|
||||||
|
- 把评分函数输出到调试 HUD,观察每项惩罚占比。
|
||||||
|
- 借鉴 RVO2,把明显危险的速度直接剔除,再对剩余速度打分。
|
||||||
|
|
||||||
|
## 对自研算法的启发
|
||||||
|
|
||||||
|
如果要写更好的 FishROV 避障算法,可以把学习版当成骨架:
|
||||||
|
|
||||||
|
```text
|
||||||
|
目标速度
|
||||||
|
-> 候选速度生成
|
||||||
|
-> 风险预测
|
||||||
|
-> 多目标评分
|
||||||
|
-> 速度平滑和运动约束
|
||||||
|
```
|
||||||
|
|
||||||
|
后续真正要优化的,是三个核心点:
|
||||||
|
|
||||||
|
- 更准确的风险函数。
|
||||||
|
- 更聪明的候选速度生成。
|
||||||
|
- 更稳定的冲突解除策略。
|
||||||
150
FishROV/Docs/unity-navmesh-core-principles.md
Normal file
150
FishROV/Docs/unity-navmesh-core-principles.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# 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、采样速度、势场、学习策略。
|
||||||
|
- 运动表现层:速度平滑、朝向约束、最大加速度。
|
||||||
|
|
||||||
|
这样能避免把所有问题都塞进一个局部避障算法里。
|
||||||
Reference in New Issue
Block a user