游戏中的人工智能之流场寻路
流场简介
流场,一般为网格图,网格中的每一个节点包含一个向量,该向量是物体在该位置时期望的速度。
流场寻路
利用流场的速度信息指导大量物体同时进行寻路。换句话说,如何生成可以寻路的流场,才是问题的关键。
这里有一篇英文的文章和一个示例[3],阅读文章有助理解流场寻路,英文不够好的同学也可以从例子中获取感性的认识。
流场寻路
在线示例
流场的简单生成:
流场根据迪杰斯特拉图生成的,而迪杰斯特拉图是依据众多智能移动体共同目的地以及节点运动消耗图生成。
节点运动消耗图,用0表示可正常通过,用极大值表示障碍物,用其他值表示河水,沼泽,斜坡,树林等地形信息。
首先,需要依据节点运动消耗图以及众多智能移动体共同目的地生成迪杰斯特拉图。
迪杰斯特拉图中的每一节点包含其距离目的地节点的最少运动消耗。
细节就是以目的地为起点进行迪杰斯特拉算法搜索到图中其他所有节点的最短运动消耗,其他非目的地节点保存这到目的节点的最短运动消耗。
什么迪杰斯特拉算法,请参看。
迪杰斯特拉算法
需要注意的是,本文中的例子生成的迪杰斯特拉图,其实使用广度优先算法生成的,这是因为边权值全部为1(路径消耗均为1)。
其次,依据迪解释特拉图生成流场。流场每一个节点包含一个指向某个邻居节点的向量,并且该向量所指向的邻居节点,在所有邻居节点中其距离目的路径消耗最少。而向量的大小可以为移动智能体的最大速率,或者单位化。
流场寻路其他细节:
-
当位于流场某一位置时,如何选取对应的速度向量,可以使用简单的归整法获取速度向量。 也可以采用双线性内插法依据上下左右其他四个节点值来计算[1]。
什么是线性内插?请参看线性内插
-
流场的生成的速度向量不一定完全最佳,可以使用一些修正算法,比如视线修正法[2],来适当的调节速度向量的方向或者无视流场给出的方向。
-
流场可以和其他行为结合起来,实现更复杂的组合操控行为。例如,流场+群聚(分离,聚集,对齐)。这一点在Game AI Pro - Efficient Crowd Simulation for Mobile Games给出了具体的实现思路。
- 流场一旦生成,就可以常数时间(每个个体不在寻路,只是查询流场)支持任意数量移动智能体寻路。地形变更或目的地变更才需要重新生成流场,在一些情况下可以缓存流场或提前生成流场以备用。比如把常用的几个目的地流场缓存,目的地变更无需再次生成流场[2]。
- 流场可以使用其他算法生成如theta*[1][6]。 什么是theta*,请参看 theta*
流场寻路的应用:
“最高指挥官2”和“坚守阵地2”这两款游戏肯定是用了流场寻路。最近比较火的“皇室战争”也可能使用流场寻路(当然我猜的)。其实,流场寻路适合两种类型的游戏RTS和MOBA(即时战略和塔防),说白了最适合大量智能运动物体拥有共同目的地寻路。
结语
大家可以轻易的发现,HowToRTS例子有很多明显的问题,我在研究时做了一些优化。包括如下内容:
- 加了移动智能体之间的分离力,这样运动起来不会扎堆,具体如何实现复杂的组合操控行为,可以采用加权截断总和,带优先级的加权截断累计,带优先级的抖动[4]。我使用带优先级的加权截断累计方式。
- 禁止移动智能体两障碍物之间斜对角线穿行。
- 实时更新目的地节点,鼠标点击地图切换目的地,重新生成流场等。
- 把移动智能体的图像改成了草莓。
用浏览器就可以下载HowToRTS示例代码,我建议大家自动动手改一改玩一玩。
参考文献:
[1]Graham Pentheny,Game AI Pro : Efficient Crowd Simulation for Mobile Games
[2]Elijah Emerson,Game AI Pro :Crowd Pathfinding and Steering Using Flow Field Tiles
[3]https://howtorts.github.io/2014/01/04/basic-flow-fields.html
[4]Mat Buckland,游戏人工智能编程案例精粹
[5]Daniel Shiffman,代码本色-用编程模拟自然
[6]http://aigamedev.com/open/tutorial/theta-star-any-angle-paths/
后记
早年的一些RTS,比如红色警戒,帝国时代2,星际争霸都被寻路的性能问题各种折磨。
帝国时代2的农民,反应延迟非常严重(一个接一个的寻路)。
星际争霸一队只有12个单位(同时寻路,但无法支持更多单位同时寻路)。
红色警戒2部队多了直接死机。流场寻路专治RTS寻路各种不服。
原创文章,谢绝转载。