寻路建模的三种方式比较

概述

本文对于游戏寻路中主流的三种建模方式做了比较,分析各自的适用范围和优缺点。这三种建模方式包括:格子(Grid)、路点(Waypoint)、导航网格(Navmesh)

写这篇的原因是项目里需要选择一种合适的寻路实现方案,查阅了大量的文章和算法后,结合着自己的思考和实践,在此做个小结。

这里的建模指的是为地图寻找一个空间表征(spatial representation)1,即把原始地图转换成计算机数据结构表示的模型,用于后面的寻路。注意它与寻路算法2是不同的概念,例如:Grid和Navmesh是两种不同的建模方式,但是建模完成后,都可以用到A*算法。

下面是三种建模方式的图形化表示,一目了然,分别是:(a) 原版地图,(b) 格子,(c) 路点,(d) 导航网格。

寻路建模的三种方式比较_第1张图片

先来一个简单而粗略的比较,后面再分头细说:

  • 实现复杂度:导航网格 > 格子 > 路点
  • 内存和计算开销3:格子 > 导航网格 > 路点
  • 表达精确性:导航网格 > 格子 > 路点

格子(Grid)

这种方法将原始地图分割成许多的小格子,在计算机中表示为一个二维数组,用0和1分别表示障碍和可行走区域。

格子的优点
  • 容易实现
  • 容易动态修改。如果需要动态加入障碍,只需要确定障碍物会占用哪些格子,再重新寻路即可。
格子的缺点
  • 内存和计算开销大。越大的地图,所需格子就越多,相应的内存占用和寻路计算开销就会越大。另外,格子的大小选择也是一个问题,定得小了,内存和计算开销大;定得大了,又会缩减可行走区域,导致可行走边界不够精确。
  • 可能需要做额外平滑。如果按照格子来寻路,最后生成的路线很可能会出现90度的拐角,甚至可能有连续的多个,这种急转弯会使得游戏寻路表现得“不够自然”。这时还需要做额外的平滑。
  • 不太适合3D地图。格子最早是针对2D地图寻路提出的,不涉及高度信息,因此没有导航网格中的maxClimbagentHeight等参数,更没有考虑分层地图。当然也不是完全不能做,只是更复杂。

路点(Waypoint)

这种方法会在地图中标注一些路点,寻路只能发生在路点和路点之间,在计算机中表示为一张连通图。

路点的优点
  • 实现简单
  • 内存和计算开销低。路点只使用到了真实可行走区域的一小部分,与格子相比,牺牲了路线的灵活性,换取较低的内存和计算开销。
路点的缺点
  • 需要人工参与。因为需要人工标注路点位置和可行走路线。
  • 局限性较大。首先,路点的灵活性较低,寻路必须沿着预先定义好的路线前进,使用时有时会发现:明明有看上去更直接的路线,却偏偏只能绕远路走折线;其次,对于起始点不在路点图中的情况,还需要找到最近的路点先移动过去;最后,路点不考虑实际的底层地图,所以在移动过程中有可能出现被物体阻挡卡住的情况。

导航网格(Navmesh)

这种方法使用一系列算法将原始地图转换成三角形网格的集合,网格和网格之间构成连通关系用于寻路。在计算机中表示为顶点的集合,以及三个顶点索引一组(边)的集合。

导航网格的优点
  • 能精确地表征世界。虽然导航网格也做不到百分百还原真实地图,但是它无疑比格子和路点都更精确。首先,它引入了高度信息,使得表示3D地图成为可能;其次,它在应用agentRadiusagentHeight等参数时用到了体素(voxel)4,这是一种比格子更小的计量单元,使得计算可行走范围时更加精确。
  • 内存和计算开销小。导航网格将地图抽象成三角网格,也就是顶点和边的集合。理论上,这种建模方式的复杂度介于路点和格子之间。
导航网格的缺点
  • 复杂,难以实现和修改。自己从头实现一个导航网格系统无疑是非常复杂的,这需要很多几何算法的知识。好在现在有一些开源的实现,如crisis的引擎工程师实现的recast-navigation5。但如果想在它基础上去修改和定制,还是要花费不少功夫。
  • 建立网格的过程耗时耗内存。与格子和路点不同,前两者从原始地图建模的过程几乎是瞬间完成的,而建立导航网格则是一个相对复杂和耗时的过程,其中体素化这一步又会占用不少内存(完成后会释放掉)。好的网格导航实现可以将建网格和动态加入障碍的时间代价控制在几毫秒的级别。通常的程序实现会在第一次寻路前就寻找时机建好网格。

总结

每种建模方式都有自己的优点和缺点,应具体根据应用场景选择合适的方式。

如果开发时间有限,需要在可能动态变化的2D地图中寻路,地图不会太大,内存充足,且对行走区域的精确度没有太高要求,首选格子。

如果开发时间有限,寻路线路相对固定(典型的如塔防游戏),不用考虑真实地形的影响,优先考虑路点。

如果开发时间充裕,地图很大,对表征真实世界的精确度要求很高,那么最好选择导航网格。


  1. 本文写作过程中参考了《游戏人工智能》中的《选择一个寻路空间表征》一文。 ↩
  2. 游戏中的常用寻路算法参见文章。 ↩
  3. 这里只针对寻路本身,不包括建模的过程,否则导航网格的开销会更大 ↩
  4. 参见我翻译的有关体素化的文章。 ↩
  5. 参见我写的专栏:recast源码解析。 ↩

你可能感兴趣的:(寻路)