摘自:https://blog.youkuaiyun.com/weixin_44489823/article/details/89382502
1:之前没有真正的理解A*算法的原理,于是就找各种博客对A*算法进行原理上的理解,毕竟理解了对以后做寻路啊等会有很大帮助,为了以后忘记了还可以重新温习一遍;
2:绿色的块块代表起始点,红色的快快代表是终点,蓝色的快快代表墙
3:如果我们需要寻路,我们当然是想找一条最短路径到达终点,难道还要绕个大湾在抵达终点吗,哈哈
4:ok废话不多说,开始探索
先明白这几个字段的概念:
1:OpenList:可以理解为开放列表,之后需要对开放列表进行遍历,找到最小的那个F值
2:CloseList:可以理解为不需要关注的列表
3:节点:因为没一个节点都有8个小方块指向自己,可以默认为自己成为了父节点
4:G:从起点 A 移动到指定方格的移动代价,沿着到达该方格而生成的路径
5:H:从指定的方格移动到终点 B 的估算成本。这个通常被称为试探法,有点让人混淆。为什么这么叫呢,因为这是个猜测。直到我们找到了路径我们才会知道真正的距离,因为途中有各种各样的东西 ( 比如墙壁,水等 ),最短抵达终点的距离,当然只能水平和垂直方法 。
6:F:F = G+H,利用这个值来做寻路排查的标记
5:详解图:
寻找节点,在根据节点,去寻找有没有在更换路径之后更小的G值,有的话,那么就更新当前的G值和F值并且更新箭头指向,在从Openlist寻找最小的F值,继续遍历,最终找到最优的路径
寻路关键代码:
/// <summary>
/// 使用A*算法寻路
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
void FindPath(Vector2 start,Vector2 end)
{
//和A*算法无关,只是为了显示使用
int showFindNum=1;
//开启列表
List<Cell> openLs = new List<Cell>();
//关闭列表
List<Cell> closeLs = new List<Cell>();
//起点
Cell startCell = grid.GetCell(start);
//终点
Cell endCell = grid.GetCell(end);
Debug.LogFormat("寻路开始,start({0}),end({1})!",start,end);
//将起点作为待处理的点放入开启列表,
openLs.Add(startCell);
//如果开启列表没有待处理点表示寻路失败,此路不通
while(openLs.Count>0)
{
//遍历开启列表,找到消费最小的点作为检查点
Cell cur = openLs[0];
for (int i = 0; i < openLs.Count; i++)
{
if(openLs[i].fCost<cur.fCost&&openLs[i].hCost<cur.hCost)
{
cur = openLs[i];
}
}
Debug.Log("当前检查点:" + cur.ToString()+" 编号:"+showFindNum+" open列表节点数量:"+openLs.Count);
//显示在界面,和A*算法无关
cur.obj.transform.Find("Num").GetComponent<Text>().text=showFindNum.ToString();
showFindNum++;
//从开启列表中删除检查点,把它加入到一个“关闭列表”,列表中保存所有不需要再次检查的方格。
openLs.Remove(cur);
closeLs.Add(cur);
//检查是否找到终点
if(cur==endCell)
{
Debug.Log("寻路结束!");
grid.CreatePath(cur);
return;
}
//根据检查点来找到周围可行走的点
//1.如果是墙或者在关闭列表中则跳过
//2.如果点不在开启列表中则添加
//3.如果点在开启列表中且当前的总花费比之前的总花费小,则更新该点信息
List<Cell> aroundCells = GetAllAroundCells(cur);
foreach (var cell in aroundCells)
{
if (cell.isWall || closeLs.Contains(cell))
continue;
int cost= cur.gCost+ GetDistanceCost(cell, cur);
if(cost<cell.gCost||!openLs.Contains(cell))
{
cell.gCost = cost;
cell.hCost = GetDistanceCost(cell,endCell);
cell.parent = cur;
Debug.Log("cell:" + cell.ToString() + " parent:" + cur.ToString() + " " + cell.PrintCost());
if(!openLs.Contains(cell))
{
openLs.Add(cell);
}
//显示在界面,和A*算法无关
cell.obj.transform.Find("Cost").GetComponent<Text>().text = cell.fCost.ToString();
}
}
}
Debug.Log("寻路失败!");
}