A*寻路(1)——理论知识

提示:个人学习总结

目录

一.A*寻路是用来解决什么问题

二.基本原理

三.详细原理

四.参考视频


一.A*寻路是用来解决什么问题

A*寻路是用来计算玩家行进路径的,通过它可以计算出避开阻挡的最短路径

二.基本原理

如图,玩家的起点是黄色区域,终点是蓝色区域,红色是阻挡区域,白色为可行走区域

玩家从a点开始移动时,会找到起点a旁边的a1~a8八个点,如果是阻挡区域和边界,就不去管它。

找周围的点时,是不会去找边界和阻挡点的排除掉边界和阻挡点后,将其他点选出来找到一个最优的点。如我们找出的最优点是a5,a5就会成为我们新的起点,然后再去寻找a5旁边的八个点,a5旁边有我们上次就找过的点,那么这次我们就不去找已经找过的点,只去找哪些没有找过的点,我们把a5当做b点,就会找到b1~b3的点:

然后就继续去找一个最优点,如我们这次找到的最优点是b1,那么就会重复之前的操作,继续去找到b1旁边的八个点,排除掉边界和阻挡点后,找出一个最优点

以此类推,最后到达终点的位置。所以A*寻路的基本原理就是不停的找自己周围的点,找出一个新的点作为起点再循环的去找。

三.详细原理

要知道A*的详细原理,有四个点是非常重要的

1.寻路消耗公式

f(寻路消耗)=g(离起点的距离)+h(离终点的距离)

2.开启列表

3.关闭列表

4.格子对象的父对象

开启和关闭列表中的列表我们可以理解为两个容器,我们的起点a点是我们的第一个点,它是没有父对象的,所以我们把它放到关闭列表中,记为null:

之后我们找到a点旁边的八个点,即a1~a8,a3为阻挡点,我们不用管他,然后我们把除a3之外点放入开启列表中:

接着就要用到我们的寻路消耗公式了,g就是我们离起点的距离

假设我们每个格子的长度是1,我们很容易就可以看出a2,a4,a5,a7四个点的g是多少,因为它们和起点a的距离都是一个格子,所以这四个点的g都是1,十字的格子很容易就得出了,那么斜着的格子呢?

通过划线我们可以看到,将三点连起来的话是一个直角三角形,两条直角边的长度都是1,通过勾股定理就可以得到斜边的长度为根号2~=1.4,斜着4个点的g为1.4。

g我们已经算出来了,接下来我们算h(离终点的距离)

那a2举例,它到终点的距离如下:

那么a2到终点的距离就是5,以此类推

g和h我们都得到了,就可以算出每个点的f(寻路消耗)

上面说是寻找一个最优的点,就是通过每个点的寻路消耗f进行对比,找出f最小的,上面a2和a5都是6,这两个点用哪个都可以,现在我们假设经过排序得出的结果是a5,那么我们就将a5放到我们的关闭列表中

还有一个点就是这些格子对象的父对象,a1~a8是从a点开始找的,所以这些点的父对象就是a,我们后面会用到它

a5作为我们新的起点,我们将它命名为b,他会重新去找它旁边的点,它在重新找点的时候,如果周围的点已经在开启列表或者关闭列表中了,我们就不去管它了,所以b点找出来的只有三个点

我们再计算出b1~到b3的g值,这个时候要注意一下,我们以b1为例,我们的起点b的父对象为a,那么b1的g值就是a到b的距离加上b到b1的距离,也就是1+1.4=2.4,其他两个点也是一样的规则,h值的计算方式和前面是一样的,这里就不在说明,计算出来之后我们记录一下他们的g值,h值和f值,然后选出最小的放入我们的关闭列表中

对比发现b1是最优的点,我们将它命名为c,继续重复之前的步骤

c3命名为d,继续找

d4这个点就是终点,它的h值是零,消耗f也是最少的,这样我们就找到了终点,我们把它也放到我们的关闭列表中

这里有一个比较重要的点就是每次我们往关闭列表中放点时,我们都应该判断这个点是不是和终点一样,如果是一样的证明路径找完了,如果不一样,继续找。

到现在我们的路径已经找完了,那么我们怎么获取这条路径呢?我们把找到的所有最优点连接起来如下图

可以发现这几个点都在我们的关闭列表中,那么我们直接从关闭列表中将它们拿出来不就行了嘛,答案是不行。我们获取最终路径并不是从关闭列表中去直接拿,还记得我们上面提到的四个点中的最后一个点嘛,格子的父对象,我们可以想一下,我们拿到了终点,就可以知道终点的父对象,终点父对象的父对象,终点父对象的父对象的父对象,这样一层一层的找,最后是不是就找到了我们的起点,因为我们的起点是没有父对象的,其实就是一个单链表的形式,通过这样的方式拉出来一个路径就是我们的最终路径,可能有人会觉得这和直接从关闭列表中拿好像没有什么区别,其实不是这样的,我们举个列子

我们就拿上面这个图举例,我们新加一片阻挡区域,然后重新走一下前面的流程,到找到c点之前和上次是一样的,找到c点之后我们原来找到的最优c3现在是一个阻挡的点,我们这次就不能再用了,包括c4,c5都是阻挡点,我们把这几个点去掉,这个时候我们只有c2这个点,所以最优是c2,而c2点的旁边是阻挡点,它就会找到它上面的点,也就是下面图中绿色的点

那这个时候问题就来了,绿点的旁边依然是一个阻挡点,那么它就会继续往旁边去找其他的点,然后绕了一大圈之后会找到b3是离终点最近的点,然后从b3再开始找

在这个过程中,我们的关闭列表中的有些点就不是我们最终路径的点,而是在寻路过程中出现的错误的点,如果什么直接拿关闭列表中的点肯定是不对的,因为其中有一些多余的点。但是如果我们通过父对象来一层层往上拉的话就会得到的路径就是这样的

而在寻路过程中出现的误差点是不在我们拉出来的路径上的,上面就是A*的一些关键点和它的原理。

四.参考视频

原视频链接:【【手把手教你】Unity中实现A星寻路算法】https://www.bilibili.com/video/BV147411u7r5?vd_source=42f4411b8309016e682f2d58e46aaba7

猜你喜欢

转载自blog.csdn.net/2302_76830411/article/details/132595418