组成部分

- 导航网格(即 Navigation Mesh,缩写为 NavMesh)是一种数据结构,用于描述游戏世界的可行走表面,并允许在游戏世界中寻找从一个可行走位置到另一个可行走位置的路径。该数据结构是从关卡几何体自动构建或烘焙的。
- 导航网格代理 (NavMesh Agent) 组件可帮助您创建在朝目标移动时能够彼此避开的角色。代理使用导航网格来推断游戏世界,并知道如何避开彼此以及移动的障碍物。
- 网格外链接 (Off-Mesh Link) 组件允许您合并无法使用可行走表面来表示的导航捷径。例如,跳过沟渠或围栏,或在通过门之前打开门,全都可以描述为网格外链接。
- 导航网格障碍物 (NavMesh Obstacle) 组件可用于描述代理在世界中导航时应避开的移动障碍物。由物理系统控制的木桶或板条箱便是障碍物的典型例子。障碍物正在移动时,代理将尽力避开它,但是障碍物一旦变为静止状态,便会在导航网格中雕刻一个孔,从而使代理能够改变自己的路径来绕过它,或者如果静止的障碍物阻挡了路径,则代理可寻找其他不同的路线。
什么是可行走区域
当我们希望智能地移动游戏中的角色(或者 AI 行业中所称的AGENT)时,必须解决两个问题:如何推断关卡来寻找目标,然后如何移动到该位置。这两个问题是紧密相关的,但性质却截然不同。关卡推断问题更具全局性和静态性,因为需要考虑整个场景。移动到目标更具局部性和动态性,只考虑移动的方向以及如何防止与其他移动的代理发生碰撞。
导航系统需要自己的数据来表示游戏场景中的可行走区域。可行走区域定义了代理可在场景中站立和移动的位置。在 Unity 中,代理被描述为圆柱体。可行走区域是通过测试代理可站立的位置从场景中的几何体自动构建的。然后,这些位置连接到场景几何体之上覆盖的表面。该表面称为导航网格(简称 NavMesh)。
导航网格将该表面存储为凸多边形。凸多边形是一种有用的表示,因为我们知道多边形内的任意两点之间没有障碍物。除了多边形边界之外,我们还存储有关哪些多边形彼此相邻的信息。这使我们能够推断整个可行走区域。
Unity的寻路使用什么算法
要寻找场景中两个位置之间的路径,我们首先需要将起始位置和目标位置映射到各自最近的多边形。然后,我们从起始位置开始搜索,访问所有邻居,直到我们到达目标多边形。通过跟踪被访问的多边形,我们可以找出从起点到目标的多边形序列。一种寻路的常用算法是 A*,这也是 Unity 使用的算法。
构建导航网格
从关卡几何体创建导航网格的过程称为导航网格烘焙 (NavMesh Baking)。该过程收集所有标记为 Navigation Static 的游戏对象的渲染网格和地形,然后处理它们以创建近似于关卡的可行走表面的导航网格。
在 Unity 中,导航网格生成方式是在 Navigation 窗口(菜单:__Window__ > AI > __Navigation__)中进行处理的。
为场景构建导航网格可以通过 4 个快速步骤完成:
- 选择应影响导航的场景几何体:可行走表面和障碍物。
- 选中 Navigation Static 复选框以便在导航网格烘焙过程中包括所选对象。
- 调整烘焙设置以匹配代理大小。
- Agent Radius 定义代理中心与墙壁或窗台的接近程度。
- Agent Height 定义代理可以达到的空间有多低。
- Max Slope 定义代理走上坡道的陡峭程度。
- Step Height 定义代理可以踏上的障碍物的高度。
- 单击 Bake 以构建导航网格。


每当 Navigation 窗口打开且可见时,生成的导航网格便会在场景中显示为底层关卡几何体上的蓝色覆盖层。
您可能已经在上面的图片中注意到,生成的导航网格中的可行走区域显示为缩小状态。导航网格表示代理中心可进行移动的区域。从概念上讲,无论将代理视为缩小的导航网格上的点还是全尺寸的导航网格上的圆都无关紧要,因为这两者是等效的。但是,解释为点有助于提高运行时效率,并可让设计人员立即看到代理是否可以挤过间隙而不用担心代理半径问题。
另外要记住的是导航网格是可行走表面的近似形状。例如,在楼梯中就能看出这一点:楼梯表示为平坦表面,但原始表面是有台阶的。这种表示方式是为了使导航网格数据大小保持较小。这种近似表示方式的副作用是,有时您会希望在关卡几何体中留出一些额外的空间,让代理能够通过一个狭窄位置。
烘焙完成后,您将在一个与导航网格所属场景同名的文件夹中找到导航网格资源文件。例如,如果在 Assets 文件夹中有一个名为 First Level 的场景,则导航网格将位于 Assets > First Level > NavMesh.asset。

技巧:附加加载网格
默认情况下,不同场景中的导航网格未连接。使用 Application.LoadLevelAdditive() 加载另一个关卡时,需要使用网格外链接 (Off-Mesh Link) 连接不同场景中的导航网格。

在此示例中有两个场景:_Scene 1_ 和 Scene 2。Scene 1 有一个网格外链接从一个可行走区域开始,并在 Scene 2 中的一个可行走区域上着陆。可根据需要设置多个连接场景的网格外链接。
在创作时,连接场景的网格外链接的另一个端点是未连接的。加载新场景后将重新连接网格外链接。

如果多个场景的导航网格在同一区域重叠,则位置选取对象可能是该位置的任意导航网格。此情况适用于使用导航网格 API 的代理、网格外链接和位置选取。应该创建跨越网格外链接的场景,使这些链接仅在一个导航网格上明确开始和结束。重叠的导航网格区域不会自动连接。
导航网格障碍物
导航网格障碍物 (Nav Mesh Obstacle) 组件允许您描述导航网格代理在世界中导航时应避开的移动障碍物(例如,由物理系统控制的木桶或板条箱)。当障碍物正在移动时,导航网格代理会尽力避开它。当障碍物静止时,它会在导航网格中雕刻一个孔。导航网格代理随后将改变它们的路径以绕过障碍物,或者如果障碍物导致路径被完全阻挡,则寻找其他不同路线。
属性 | 功能 |
---|---|
Shape | 障碍物几何体的形状。选择最适合对象形状的选项。 |
Box | |
Center | 盒体的中心(相对于变换位置)。 |
Size | 盒体的大小。 |
Capsule | |
Center | 胶囊体的中心(相对于变换位置)。 |
Radius | 胶囊体的半径。 |
Height | 胶囊体的高度。 |
Carve | 勾选 Carve 复选框后,导航网格障碍物会在导航网格中创建一个孔。 |
Move Threshold | 当导航网格障碍物的移动距离超过 Move Threshold 设置的值时,Unity 会将其视为移动状态。使用此属性可设置该阈值距离来更新移动的雕孔。 |
Time To Stationary | 将障碍物视为静止状态所需等候的时间(以秒为单位)。 |
Carve Only Stationary | 启用此属性后,只有在静止状态时才会雕刻障碍物。请参阅下面的移动的导航网格障碍物的逻辑以了解更多信息。 |
什么是Carve参数
未启用 Carve 时,导航网格障碍物的默认行为类似于碰撞体的行为。导航网格代理会尝试避免与导航网格障碍物的碰撞,当靠近时,它们会与导航网格障碍物碰撞。障碍躲避行为是非常基本的,具有一条短半径。因此,导航网格代理可能无法在导航网格障碍物很混乱的环境中找到方向。此模式最适合用于障碍物不断移动的情况(例如,车辆或玩家角色)。
启用 Carve 时,障碍物处于静止状态时将在导航网格中雕刻一个孔。移动时,障碍物即为障碍物。在导航网格中雕刻一个孔后,寻路器 (pathfinder) 能够让导航网格代理绕过雕有障碍物的位置周围,或者如果当前路径被障碍物阻挡,则寻找另一条路线。对于通常会阻碍导航但可被玩家或其他游戏事件(如爆炸)移动的导航网格障碍物(例如板条箱或木桶),最好为其开启雕刻功能。
移动的导航网格障碍物的逻辑
当导航网格障碍物的移动距离超过 Carve > Move Threshold 设置的值时,Unity 会将其视为移动状态。当导航网格障碍物移动时,雕刻的孔也会移动。但是,为了减少 CPU 开销,只在必要时才重新计算该孔。此计算的结果将在下一帧更新中可用。重新计算逻辑有两个选项:
- 仅当导航网格障碍物静止时才进行雕刻(勾选Carve Only Stationary)
- 导航网格障碍物移动后进行雕刻(不勾选Carve Only Stationary)