基于tilemap,生成2D平面的三角形组成的navigation mesh

    最近在tilemap上搞地图,进展到AI寻路的问题,然后就想到AStar,AStar需要一个关键的数据结构就是导航格,于是一直在思考如何在tilemap上形成导航网格,有人可能会联想到直接用tilemap上的tile进行导航,但是我个人包括很多开发者觉得这样做不仅不灵活,而且会带来很多后续问题。于是联想到了现在更多采用的navigation mesh。

    如何在tilemap上生成navigation mesh,这个问题其实从一开始做AI开始,就一直困扰自己,经历了很多次纠结以后,最终我的解决方案思路可以分为以下几步:

1. 用tilemap的对象层里面的polyline逆时针拖拽出障碍物的包围(我这里会使用一个方法,即强制使poliyline的最后一个vertex等于第一个vertex, 闭合这个polyline使其变成一个polygon),最外围的包围边界则使用顺时针的方法拖拽出一个polygon。存储这里所有的polygon的所有vertex到_verticesForNavMeshGen, 所有edge到_edgesForNavMeshGen

2. 遍历_edgesForNavMeshGen, 对于每个edge,取_verticesForNavMeshGen中的在其右侧并且距离他最近vertex,并且不和_edgesForNavMeshGen中任何一条除这个包含vertex和edge本身之外的edges会有交点。

3. 步奏2中的edge和vertex形成一个三角形,加入_navigationMeshTriangles中,并且产生出两条新的newEdge1和newEdge2(逆时针的方向,外围包围框则为逆时针方向,这里只要步奏1中的生成方式正确,按照AB,AC, CB来组合三角形就可以)

4. 把edge从_edgesForNavMeshGen中剔除

5. 将newEdge1和newEdge2加入_edgesForNavMeshGen仅当以下条件成立:newEdge不和_edgesForNavMeshGen中的任何edge相等(相等条件是两条edge有相同的两个vertex,方向无关),如果不成立,则表示此newEdge和这条edge重合,这条edge可以通过这个新三角形到达,则把此edge从_edgesForNavMeshGen中剔除。

6. 转至步奏2,直到_edgesForNavMeshGen为空,最终得到的_navigationMeshTriangles就是一个三角形构成的navigation mesh。


ps:其实一开始想生成convex凸多边形的集合,但好像有点难度,最后觉得先从简单的三角形集合入手,也许以后会进行进一步的三角形合并凸多边形的优化。


以上是基本思路


下图是当时在tilemap整理思路的时候画的图

基于tilemap,生成2D平面的三角形组成的navigation mesh_第1张图片

下图是真实游戏内形成的navigation mesh

基于tilemap,生成2D平面的三角形组成的navigation mesh_第2张图片



下面是生成过程中关键的数据结构

Vertex:构成包围的所有点,在生成navigation mesh过程中不会新增

Edge:由两个Vertex组成,在判定三角形是否邻接时,使用IsEqual的方法,该方法判断两个Edge如果有相同的Vertex并且无关方向,则返回true。在生成navigation mesh过程中会增加

Triangle:由3个Edge组成,每个Edge的方向为顺时针(或者逆时针,保证三条边方向一致就行),这样做是为了以后判断 点 是否在三角形内。


你可能感兴趣的:(基于tilemap,生成2D平面的三角形组成的navigation mesh)