Navigation AI:游戏中最常见的AI应用之一,即导航系统,自动寻找一点到另一点位置的路线。
Navigition系统包含的三个步骤:理解地图,寻路,路线平滑化。
Map Representations-walkable area:理解地图,首先就要让AI知道哪些路是可以通过的。这需要考虑到很多要素,不仅是可以直接通过的位置,还有小坡,跳跃距离,物理碰撞等等。表达walkable area的方法有很多,如路网,网格,八叉树等等。不同的表示方式可能需要不同的对应寻路算法。
WayPoint Netwalk(路网):在地图中插入多个点和点之间的连接路线,用于表示可以走到的位置。寻路时角色会先找到离起点和终点最近的关键点或连接路线,再从该位置开始沿连接路线行走。魔兽世界就采用了这种寻路方式(寻路过程可以采用dijistra算法(点到其它所有点最短路径)或Floyd算法(所有点到所有点的最短路径,可以事先算好存储在电脑中)等实现)。
优点:易于实现,运行效率高;
缺点:设计师需要手动设置关键点,且npc行为在关键点稀疏的情况下行进路线会变得非常奇怪,现在一般只适用于一些只需要简单寻路的游戏。
Grid:用足够细密的网格盖在地图上,用网格化的方式寻找路线。
优点:易于理解,且世界地图发生改变时也易于更新。
缺点:对存储空间浪费较大,格子密度大时计算也会变得困难,且难以表达带Z轴的3D层叠结构。
Navigation Mesh:最普遍的寻路算法,将所有可通行的区域用多边形mesh表示,根据不同区域间的连接关系构成图并寻路。现代游戏引擎一般会自带navigation mesh自动生成算法,使寻路结构的形成更加方便。
要求:每个格子的多边形必须是凸多边形,且每两个凸多边形之间只有一个共享边。
优点:支持3D,精确且寻路效率高,区域大小和形状灵活(一个polygon可以用于表达大块的区域),可动态更新。
缺点:生成过程复杂(一般都需要预先生成好),不支持纯3D空间的导航(如一些3D空战游戏中飞机从一点到另一点的导航)
空间八叉树:用空间八叉树分割3D空间,从而表达3D空间可通行区域。
缺点:所需的存储空间非常大,且寻路算法也非常地麻烦。
寻路算法:深度优先/广度优先算法,Dijkstra算法,A*算法等
A*算法:最经典的常用算法,在已走距离的基础上加入预测距离,每次选取两者相加最小的点。预测距离可以用欧拉距离等方法来预测。在NaviMesh里的实现比较复杂,会将各个polygon之间的连接边的中点之间的连线作为路径来计算。其预测距离也是用欧拉距离来算。对未来路径距离的估计过于保守时(使用非常严格的预测,如逐点之间计算距离),更可能找到最短路径,但速度会下降;过于激进时(如不考虑障碍物,直接用两点间欧拉距离作为预测距离),可能找不到最短路径,但计算速度会非常快。
Path Smoothing:
为了使行动更加真实一些,需要通过path Smoothing来平滑路径从而去掉不必要的行走。
Funnel Algorithm:模拟人视野范围的一种算法,一般用于二维空间的寻路。从起点连接到下一个多边形的连接边的两个端点,形成一个扇形区域,判断下一个polygon是否完全在扇形区域里,若在内部,则再通过下一个连接边从而确定新的扇形区域,并判断下下个多边形是否完全在里面并确定新的行走路径 。直到不完全在内部时,通过连接起点到连接边两端形成两条新的路径,判断哪个路径能离终点更近并将其作为行走路径,以该路径终点作为新的起点重复上述算法。
若终点直接在scope里面,则直接连接起点和终点作为最短路径。
三维空间下,该算法的实现会更加困难。
Navigation Mesh的生成方式:
第一步:Voxelization,将整个世界体素化
第二步:在体素中标注walkable area(相邻voxel间坡度不太大时判断两部分之间可连接)
第三步:找到edge voxel(邻居中存在不可到达的voxel)
第四步:根据voxel生成一个距离场,即在每个voxel找其最近的edge voxel并计算其距离,根据距离生成一张图
第五步:在距离场上使用洪水算法,以几个离边界相对最远的点为种子向外扩散,最终获得一个比较自然的空间划分
第六步:将每个voxel的区域变为一个个polygon,
存在的问题:每次修改地图后的regenerate不能继承上一次的结果,只能重新生成一遍
Polygon Flag:可以给每个polygon打上不同的标签,使角色走上去时能产生不同的效果,或者设置优先级或是否可使特定角色通行,一般都是设计师直接在地图上标然后映射到polygon map上。
Tile:将空间分成多个tile,当有新的障碍生成或有障碍消失时,只需要在对应的tile里重新生成一遍polygon map,这对于加快寻路速度十分有用。这对于有场景互动的游戏是十分有用的。
Off-mesh Link:有时候如一些攀爬点之类的区域用自动化navigation map生成算法是没法形成通路的,这时候需要人工将mesh之间进行连接并定义不同mesh间移动的行为。