AStar 寻路

AStar 寻路
MeteorCat这种是游戏服务端当中最常见的碰撞检测游戏寻路方式, 日常AI机器人也十分依赖寻路策略.
静态可以采用
AStar, 而动态则需要Dstar的Dijkstra处理运算寻路, 移动端游戏尽可能采用静态寻路处理
游戏客户端大部分实现这些插件让其更加易用( Unity的NavMesh ),
但是服务端则缺失这部分功能也就没办法在服务端模拟玩家行走路线从而同步.
AStar寻路实际上是采用 网格(Gird) 的寻路计算, 具体原理就是先把整个地图分解成 Width * Height 多个格子,
然后通过网格周边连线来处理出最短路径, 同时支持标识障碍物绕过计算, 这种过程就是将 平面栅格化.
大部分寻路都是基于这种方式, 只是按照不同算法评估周边格子从而采样路径处理.
注: 在空间寻路当中必须要具有
方向和距离才能形成正确的寻路路径(向量|矢量)
寻路方式按照不同方式计算寻路:
-
曼哈顿估价法(Manhattan Heuristic) -
几何估价法(Euclidean Heuristic) -
对角线估价法(Diagonal Heuristic)
对应三种寻路方式图示处理:
曼哈顿估价法
基于 四向移动(十字形位移) 的计算, 也就是只有 上下左右 方向, 这种四向计算性能消耗相对比较小但是只支持四向寻路:
1 | ---d为计算的相邻正方体网格间移动成本, 也就是从起始坐标格子位移到周边格子路径 |
几何估价法
基于 任意方向移动 的, 利用几何计算来让寻路支持任意方向位移, 但是计算开销极大:
1 | ---d为计算的相邻正方体网格间移动成本, 也就是从起始坐标格子位移到周边格子路径 |
对角线估价法
基于 八向移动(米字形位移) 的计算, 在原来 曼哈顿估价法 引入对角线移动的方式:
1 | ---d为计算的相邻正方体网格间移动成本, 也就是从起始坐标格子位移到周边格子路径 |
估价意义
上面有个名词叫 估价, 把寻路的过程当作 代价|价值, 有代价就需要对其进行评估 估算 最短需要投入的开销;
也就是需要把需要把寻路步骤量化成 价值估算,
因为从 (0,0)走向(1,1)算是走得通, 而(0,0)走(3,3)再走(1,1)也算是走得通, 关键是衡量走通的性价比.
1 | 函数公式: f(n) = g(n) + h(n) |
以下摘录网络的寻路估价计算方式
这里采用八向移动法, 支持 米字移动 方式,
从而计算路径估值代价( 绿色代表玩家, 红色代表终点, 灰色代表障碍物, 棕色代表最优选中路径网格 ):
首先是套用 f(n) = g(n) + h(n) 公式, 计算出玩家周边格子的估价, 图片如下:
1 | 这里先说明下 ( f = 3, g = 1, h =2 ) 是估价出来的: |
这里取值 ( f=3 ) 作为下一步的坐标路径, 那么要以 ( f=3 ) 继续套用公式继续计算最短路径:
这里需要计算出格子的四周和终点是否相邻,如果相邻并终止算法得出估算的路径成本, 否则计算出没有与终点相邻需要重新进行下一步估值计算.
在不断递归检索 f(n) 路径最优值的时候, 最终若干次估算得出到达终点的场值:
这就是整体的估算意义, 通过这种不断 启发性 估值出下步节点, 最终计算出最短距离来反推回起点距离;
优点就是寻路性能比较好且方便实现, 但是缺点就是实时性差且随着网格增多检索路径的效率越发变低,
所以寻路切割的尽可能不要将网格分割过于细小从而保持效率; 这里展示最后的计算路径过程:
代码实现初始化
这里主要采用 曼哈顿估值法 和 对角线估价法 就能应用日常游戏寻路方式, 而几何因为计算性能不在考虑范围内.
这里先说明下怎么采用代码实现上面 十和米字型 公式移动, 从而理解公式转代码的流程:
1 | ---二维坐标系类对象 |
以上就是单步公式套用方式最后计算周边网格 h(n) 值, 而 g(n) 取值则是需要计算内部已行走开放节点格子数值;
另外这里还需要说明位图数据标识地图信息, 这里也是用 Lua 演示如果客户端导出的地图格子通行信息的格式:
1 | -- 实例化位图网格对象 |
这里最后展示出来的就是地图的网格状态:
1 | 位图网格数据坐标, 内部如果网格值大于 0 可以识别网格状态, 比如现在标识 1 代表阻挡物, 所以寻路要避开: |
后续客户端需要开发地图编辑器提供给策划|客户端等进行地图去 刷 地图网格导出成 lua|json|python 等表格式,
从而让服务器启动|玩家登录时候加载场景地图用于 玩家|AI地图寻路.
现在大概理解了寻路要素:
-
玩家起始点 -
startPoint -
到达终点 -
endPoint -
场景位图位图 -
tiles
只要理解寻路这些要素就可以进行下一步代码部署, 下面编写个示例导出的数据格式文件用于做客户端参考:
1 | 创建编写地图导出位图, 后续要客户端暴露给 |
网格区块内容如下, 先设定个 16 * 9 的网格数据用来导出给服务端加载:
1 | // Titles = [Y][X], 这里就是个 16(X):9(Y) 比例的场地网格位图 |
那么现在就是开始解析寻路处理.
代码抽象
现在准备处理最短路径寻路编写功能:
1 | ---二维坐标象限 |
之后就是具体的 AStar 寻路工具类设计:
未完待续
地图编辑
之前看过要求平面格式化成多个小格子,而之前说到客户端开个地图编辑器通过策划刷格子标识格子可以移动|会被阻挡等状态,
最后导出成 Json|Lua 等通用位图格式提供给服务端启动生成场景在服务端构建公用地图模块寻路.
注意:
规定地图的 (X,Y) 必须能够被格子整除, 也就是如果美术地图设计出1920 * 1080, 格子块必须能被宽高整除(被2整除)
导出位图就是各自格子的分布情况, 实际上所有地图都可以进行切分小格子按比例切割 , 对于服务端来说人物寻路其实就像象棋走格子.

