ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RecastNavigation 导航网格:5 个从选型到调优的决策

RecastNavigation 导航网格:5 个从选型到调优的决策

RecastNavigation 导航网格:5 个从选型到调优的决策

【免费下载链接】recastnavigationIndustry-standard navigation-mesh toolset for games项目地址: https://gitcode.com/GitHub_Trending/re/recastnavigation

开放世界 NPC 在门口原地打转,原因多半不在行为树,而是导航网格没盖住房门,或者角色落点不在任何多边形里。RecastNavigation 的活儿就是把场景模型栅格化成可查询的导航网格,配套的 RecastDemo 能让你先把问题复现出来再谈修。

从模型文件到可查询路径

整条链路是一条没有分叉的流水线。

先说结论:模型进来,多边形图出去,中间四步各司其职。三角形被写进体素高度场,压缩成紧凑高度场后做可行走过滤,区域划分把连续可行走面切成块,轮廓提取再三角化,最后由dtNavMesh组装成带邻接关系的多边形集合。此后所有寻路、射线、最近点查询,本质都是在这张多边形图上做图搜索,不再碰原始网格。

这就是 RecastDemo 的主界面:左边是工具列表,中间是构建结果,右边每个参数实时可调——导航网格构建的全过程在这里都能看得见、摸得着。

五个示例工程(Solo Mesh、Tile Mesh 等)的构建步骤和源码接入方式,见仓库里的构建与集成文档。

🧭 两种网格模式,3 个条件对号入座

先给结论:除非要局部重建,否则选单网格,省事。

下面三条判断,逐条对号:

  1. 场景运行时会变吗→ 几何只在加载前确定,单网格足够:一次构建,后续不用管瓦片坐标和加载状态。
  2. 场景能切成固定块吗→ 开放世界、流式加载要求按需装卸区域,就得上瓦片网格:每块独立构建,卸载区域连带释放内存。
  3. 整图重建的代价能忍吗→ 全量重建在一秒内可完成,优先单网格;全量要几十秒,瓦片化让你只为一小块付钱。

瓦片网格像地图册装订:每张图独立绘制,修某条路只重印那一页,不用把整本册子重新排版。

瓦片边界填充如何保证跨块连通

瓦片接缝处路径为什么不劈叉?关键是一圈填充区。

构建单个瓦片时,RecastDemo 把取样范围向外扩出borderSize格,把邻块附近的三角形也拉进来参与过滤和区域划分;但填充区里不真正生成任何多边形——它只负责让边缘处的多边形形状和相邻瓦片对得上。就像地图装订留白:制图者每页边缘多画一厘米,路在页与页之间自然延续,留白本身却不画新内容。

// Sample_TileMesh.cpp:border 计算与取样范围外扩 m_cfg.borderSize = m_cfg.walkableRadius + 3; m_cfg.width = m_cfg.tileSize + m_cfg.borderSize * 2; m_cfg.height = m_cfg.tileSize + m_cfg.borderSize * 2; m_cfg.bmin[0] -= m_cfg.borderSize * m_cfg.cs; m_cfg.bmin[2] -= m_cfg.borderSize * m_cfg.cs; m_cfg.bmax[0] += m_cfg.borderSize * m_cfg.cs;

borderSize至少要盖过walkableRadius再加几格余量,否则边缘多边形会被侵蚀步骤削掉一角,接缝就对不上了。其余机制一句话带过:rcMarkWalkableTriangles加侵蚀负责把角色塞不进去的几何剔掉;rcGetChunksOverlappingRect用 chunky 树挑出只接触当前瓦片的三角形,避免全量扫网格。

🛠 排错实录:两次真实排查

排错永远是三段式:看到现象,切换工具,定位成因。

案例一:门口查不到多边形

看到的现象:单块内寻路正常,目标点设在门口时查询返回失败,角色停在门框边。

用工具查看:RecastDemo 里切到 NavMeshTesterTool,在门口放"Find Polys in Circle",圆形查询返回零个多边形;再切"Pathfind Follow",路径也停在门边,覆盖缺失被坐实。

定位到的成因:右侧面板显示角色半径 0.6 大于门洞实际宽度,侵蚀步骤把门口判成"塞不下"。把半径调小重建,门口覆盖立刻出现。教训是:先查多边形覆盖,再谈路径算法。

案例二:瓦片接缝处角色贴墙

看到的现象:相邻两个瓦片之间寻路能通,但角色有时在接缝处"切墙"或短暂悬空。

用工具查看:用 Tile Mesh 示例的 Create Tiles 铺出瓦片布局,配合瓦片高亮逐段确认路径归属,异常集中在瓦片边界上。

定位到的成因:取瓦片取样包围盒时没按borderSize外扩,边缘多边形和邻块的各差一角,中间出现缝隙,位置插值只好穿过去。按上一节的方式补齐填充区后,接缝多边形严丝合缝,问题消失。

参数调不对会怎样

参数调不对,要么可行走区缩水,要么路径贴角乱飞。最常翻车的五个参数如下:

参数调优方向副作用
cellSize / cellHeight调大,格子变少、构建变快细节丢失,窄可行走带被削没
walkableSlopeAngle调高,覆盖更多台阶陡坡变可行走,路径观感变差
walkableRadius调小,可行走区逼近障碍角色贴墙易卡住
regionMinSize / MergeSize合并更激进多边形更大更少,小平台被吞
edgeMaxLen / edgeMaxError放宽,顶点更少路径切角,可能"穿过"几何缝隙

构建耗时可以靠rcContext的分步计时器读数:栅格化占大头就降 cellSize,区域划分占大头就动 MergeSize,不用猜。

什么时候用它,什么时候换方案

如果你的需求是平面导航加路径查询,无论静态场景还是瓦片化动态场景,RecastNavigation 都是稳妥的选择,RecastDemo 里的工具和流程可以直接搬进自己的工具链。如果角色要攀爬、跳跃并在三维空间自由移动,或希望直接基于物理碰撞体生成导航,那就该看基于物理引擎的导航方案或别的三维寻路库。拿不准的时候,先把真实场景丢进 RecastDemo 跑一遍——十分钟的演示,比十天的集成评估更省。

【免费下载链接】recastnavigationIndustry-standard navigation-mesh toolset for games项目地址: https://gitcode.com/GitHub_Trending/re/recastnavigation

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进