[控场AI]
· 4 分钟阅读· 2,368 字

开源魔兽寻路修复实录:1332行代码填平三年老坑

开源魔兽寻路修复实录:1332行代码填平三年老坑

开源魔兽世界寻路 bug 的根因在网格生成层,而非 AI 逻辑。

文章复盘了 B 站 UP 主“大肥鱼”修复开源魔兽世界寻路 bug 的全过程。怪物卡闪避、穿墙、悬空、缺席四类乱象,根子都在地形高度查询与寻路网格的生成错误:高度查询全向搜索、多层地形无限下搜、允许穿洞口、超过 60 度的三角形被扇掉。修复思路从“删墙”转向“标记陡坡”,并经历参数审计误判、530 条手工补连丢失、高度换算取整方向错误等反复,最终通过把补连内建进生成器、按格区分参数、四舍五入改向上取整三项改动锁死 bug 链。核心启示是排查顺序应先数据生成、后运行时逻辑。

《开源魔兽世界》的寻路 bug 几乎成了“修服”圈子的活化石:怪物追人追到一半突然立定、贴着城墙穿模而过、踩着空气往天上走、该出现的怪永远缺席。B 站 UP 主“大肥鱼”在「修服日志 EP3」里披露了这套问题的完整成因与修复路径——本质不是 AI 逻辑写错,而是地形与寻路网格从生成层就烂了。

8月23号第一版规则定稿

四种乱象,一个病根

玩家视角能看到四类故障:怪物追击途中突然僵住(社区俗称“卡闪避”)、贴墙直接穿过去、悬空踩着空气上浮,以及该来巡逻的怪压根不来门道炮——后者是因为它的双绳半径只有 30 码,而巡逻点之间相距 40 到 50 码,够不着,只能原地不动。

这四类现象看似分散,根子却都在同一套东西上:地形高度查询与寻路网格。UP 主把当初 8 月 5 号分叉时的上游问题归纳为三类取向错误:高度查询是全向搜索的,把墙和天花板的背面也算成可站立地板;多层地形会无限往下搜;设置上还允许穿过洞口,把单位直接拉进地下;另外超过 60 度的三角形被直接扇掉,导致墙上出现流洞,怪物就从洞里钻了过去。

寻路网格(NavMesh) 是游戏 AI 寻路的基础数据结构,通常由地形几何体自动烘焙生成,把可行走表面抽象成由三角形或凸多边形拼接成的连通图。怪物追击玩家时,寻路系统会在这张图上做 A* 之类的搜索,再把路径点交给移动逻辑执行。因此一旦网格本身出现破洞、孤岛或错误的面片,运行时逻辑再怎么改也无法弥补——怪物要么找不到路而站住,要么把墙面误判为地板而穿模。这也是本文反复强调“先怀疑数据生成,再怀疑运行时逻辑”的原因:NavMesh 是地形与 AI 之间的中间层,它的质量直接决定了上层行为的上限。

规则定稿:不删墙,只标坡

8 月 23 号第一版规则定稿,思路从“删掉错误面”转向“标记错误面”。墙和天花板不再被删除,而是标记为陡坡挡路;矮装饰物只有在下方存在真实地面时才算可踩;移动终点一律吸附回网格表面。第二天又补掉一个符号 bug:代码取了绝对值,结果天花板底面被算成了可走地板。

真正定案要等到 9 月 29 号。到 9 月 16 号为止,这一块累计改了 27 个文件、加了 1332 行。

中间根本没有连通的路径

卡闪避的真凶:被切碎的网格孤岛

“卡闪避”一直被认为是 AI 逻辑问题,实际并非如此。网格被切成了一个个孤岛,怪物站在一块孤岛上,目标在另一块,中间根本没有连通路径——找不到路,表现出来就是站住不动。

根因有两条:两处高度查询算错,加上生成参数把窄通道切碎了。对应的修法也是两条:一是 off mesh 自动补连,把断掉的网格接上;二是每格单独给参数,窄通道和窄楼梯的半径设成一。

Off mesh link(离线网格连接) 是寻路系统里用来跨越不连通区域的补充连接,常见于跳跃点、传送门或两块独立网格之间。当自动烘焙无法把相邻区域连成一体时,开发者会手工放置 off mesh link,让寻路搜索能够“跳”过去。本文中 530 条手工补连丢失之所以致命,正是因为这些连接是外部文件形式存在的补丁,一旦生成流程没有读取它们,网格立刻退回孤岛状态,卡闪避随之复发。把补连内建为 auto off mesh、由生成器自动产出,本质上是把易丢失的外部依赖转化为可复现的生成产物。

参数审计与 530 条补连的丢失

10 月 14 号做了一次参数审计,结论有点打脸:团队以为有四条配置覆盖在生效,实际上是假的;两条故障归因是错的;还有五个格子被静默丢掉,日志里一个字都没写。

被静默丢掉,日志里一个字都没写

第二天情况更糟——改生成参数时忘了带 off mesh input,530 条手工补连全部丢失,卡闪避立刻复发。同一天,团队决定把补连直接做进生成器,命名为 auto off mesh,从此不再依赖外部文件。

生成器重做:四舍五入换成向上取整

10 月 22 号重做生成器,其中一项改动看起来极小却影响很大:高度换算从四舍五入改成向上取整。原因是四舍五入会把台阶算少一格,而 climb 参数是 50 级,一格之差就足以让整条寻路链断掉。

高度换算改为向上取整

climb 参数 指寻路网格烘焙时允许单位跨越的最大高度差,通常以体素或格为单位。高度查询把连续地形离散成格子时,取整方式会直接改变台阶的可跨越性:四舍五入可能把一级台阶算成零格,导致相邻格子的高度差超过 climb 阈值,寻路链在这一格断开。改为向上取整后,台阶至少被计为一格,虽然可能略微高估高度,但不会漏掉真实存在的落差。这类“一格之差”的问题在体素化烘焙中非常典型,也是很多寻路 bug 难以复现的原因——它只在特定台阶高度组合下才会触发。

对修服玩家的启示

这套修复最值得借鉴的不是具体参数,而是排查顺序:先怀疑数据生成,再怀疑运行时逻辑。一个“怪物追一半停住”的表象,最终追到了高度查询的绝对值、窄通道的网格参数、以及外部补连文件的静默丢失。UP 主在第三期日志里把失败过程也完整记录了下来,包括自己在参数审计上的误判,这类“反向复盘”对同样在做私服或开源项目维护的开发者价值不小。

把补连内建进生成器、把参数按格子区分、把高度换算的方向修正——三项改动叠加后,才真正锁死了这条从地形层渗进 AI 层的 bug 链。

#开源魔兽世界#寻路网格修复#off mesh自动补连#卡闪避#私服开发#寻路bug#生成器参数
分享:

相关推荐