寻路算法简介

时间:2021-11-02 04:24:39

对一个物体来说,移动很容易,而寻路很复杂。

为什么要寻找路径?考虑以下情况:

寻路算法简介

一个单位最初位于地图的底部,并希望到达顶部。

Movement - 它扫描的区域(肉色底)中没有任何阻挡表示该装置不应向上移动,因此它继续前进。在顶部附近,它会检测到障碍物并改变方向。然后它沿着(红色)路径绕过“U”形障碍物。

Pathfinding - 另一个想法是,探路者扫描更大的区域(浅蓝底),发现较短的路径(蓝色),从而避免走进凹形障碍物。

 

另外,您可以扩展移动算法以解决上面显示的陷阱问题。可以避免生成凹陷障碍物,也可以将它们的凸包标记为危险(只有在目的地位于内部时才进入):

寻路算法简介

 

寻路的搜索器希望能够提前计划,而不是等到最后一刻发现障碍。

我们需要在(Pathfinding)路径规划和(Movement)进行移动之间进行权衡。

规划通常较慢,但能给出更好的路径;运动通常更快,但可能会卡住。

如果游戏世界经常变化,那么提前规划就不那么有价值了。

我建议同时使用:在拥有大型、移动缓慢的障碍物,以及起点到目标之间有很长的路径时用 Pathfinding;在局部区域、有快速变化和较短路径时用 Movement。

算法

新页面

计科的教科书中,寻路算法,应用在图论中

图在数学意义上,是一组具有连接它们的边缘的顶点。

 

平铺的游戏地图可以视为一张图。每个平铺块都是顶点,彼此相邻的图块之间有连接的边:

寻路算法简介

 

现在,假设我们正在使用二维网格

如果您之前没有使用图表,参阅此入门手册稍后,我将讨论如何从游戏世界中构建其他类型的图形

来自AI或算法研究的大多数寻路算法,都是针对任意图形,而不是基于网格的游戏而设计的。

我们想找到一些可以利用游戏地图性质的东西。

我们认为有些事情是常识,但算法并不理解。我们对距离有所了解:一般来说,当两个东西相距较远时,假设没有虫洞,则需要更长时间才能从一个移动到另一个。我们对方向有所了解:如果您的目的地位于东方,那么走向东方的路径比走向西方更容易找到最佳路径。在网格上,我们知道关于对称性的东西:大多数时候,向北移动然后向东移动与向东移动然后向北移动相同。这些附加信息可以帮助我们更快地运行寻路算法。

Dijkstra算法和最佳优先搜索

Dijkstra 算法通过从对象的起点开始访问图中的顶点来工作。

然后,它重复检查最近的尚未检查的顶点,将其顶点添加到要检查的顶点集

从起点向外扩展,直到达到目标。

Dijkstra 算法保证找到一条从起点到目标的最短路径,只要没有边缘具有负成本。(我写的是“一条最短路径”,因为通常存在多个等效短路径。)

在下图中,粉红色方块是起点,蓝色方块是目标,蓝绿色区域显示Dijkstra算法扫描的区域。最轻的蓝绿色区域距离起点最远,因此形成了探索的“前沿”:

寻路算法简介

 

 

贪心算法(Greedy Best-First-Search)以类似的方式工作,除了它有一些估计(称为启发式,任何顶点离目标有多远。它不是选择最接近起点的顶点,而是选择最接近目标的顶点)。

贪心算法不保证找到最短的路径。

然而,它比 Dijkstra算法运行得快得多,因为它用的启发式函数非常快速地引导它朝向目标。例如,如果目标位于起始位置的南侧,则贪心算法将倾向于关注向南的路径。

在下图中,黄色表示具有高启发式值(达到目标的高成本)的节点,黑色表示具有低启发式值的节点(达到目标的低成本)。它表明,与Dijkstra的算法相比,贪心算法可以非常快速地找到路径:

寻路算法简介

然而,这两个例子都说明了最简单的情况 - 当地图没有障碍物时,最短路径确实是一条直线。

让我们考虑上一节中描述的凹陷障碍。Dijkstra的算法更加努力,但保证找到最短的路径:

寻路算法简介

另一方面,贪心的Best-First-Search做的工作较少,但其路径显然不太好:

寻路算法简介

麻烦的是贪婪的Best-First-Search是“贪心的”,试图朝着目标前进,即使它不是正确的道路。

因为它只考虑到达目标的成本忽略了到目前为止的路径成本,所以即使它会继续前进,即便所使用的路径会变得非常长。

 

将两者中最好的结合起来会不会很好?

A *是在1968年开发的,用于结合启发式方法(如贪心算法)和其他更庄重些的方法(如Dijsktra算法)。

这有点不寻常,因为启发式算法通常会为您提供一种解决问题的近似方法,而无法保证最优解。

寻路算法简介

而 A* 建立在启发式的基础之上,虽然启发式本身并不能保证,但 A* 可以保证最短的路径。

 A* 算法

我将专注于A* 算法A* 是寻路寻找最受欢迎的选择,因为它非常灵活,可以在各种环境中使用。

像 Dijkstra 算法一样,它可以用来找到最短的路径。像贪心算法一样,它可以使用启发式来指导自己。在简单的情况下,它与贪心算法一样快:

寻路算法简介

在具有凹陷障碍物的示例中,A* 可以找到与Dijkstra算法找到的路径一样好的路径:

寻路算法简介

它成功的秘诀在于它结合了Dijkstra算法使用的信息(支持接近起点的顶点)和贪心算法使用的信息(支持接近目标的顶点)。

在谈论A *时使用的标准术语,g(n)表示从起点到任何顶点的路径确切成本 nh(n)表示从顶点到目标的启发式估计成本 n

在上图中,黄色点(h)表示远离目标的顶点,蓝绿色点(g)表示远离起点的顶点。

A* 在从起点移动到目标时平衡两者。每次通过主循环,它检查 具有最低的顶点 f(n) = g(n) + h(n)

本文的其余部分将探讨启发式设计实现地图表示以及与在游戏中使用寻路相关的各种其他主题。有些部分很充实,有些则相当不完整。