当前位置: 首页 > news >正文

Unity A*算法实现+演示

注意:

本文是对基于下方文章链接的理论,并最终代码实现,感谢作者大大的描述,非常详细,流程稍微做了些改动,文末有工程网盘链接,感兴趣的可以下载。

A*算法详解(个人认为最详细,最通俗易懂的一个版本)-CSDN博客

1、效果演示:

2、A*算法流程:

(1)         把起点加入 open list 。

(2)         重复如下过程:

                        a.         遍历 open list ,查找 F 值最小的节点,把它作为当前要处理的节点。

                        b.         对当前方格的 8连通的每一个方格            

                                         ◆     如果它是不可抵达的或者它在 close list 中,忽略它。否则,做如下操作。

                                         ◆     如果它不在 open list 中,把它加入 open list ,并且把当前方格设置为它的父亲,记录该方格的 F , G 和 H 值。

                                         ◆     如果它已经在 open list 中,检查这条路径 ( 即经由当前方格到达它那里 ) 是否更好,用 G 值作参考。更小的 G 值表示这是更好的路径。如果是这样,把它的父亲设置为当前方格,并重新计算它的 G 和 F 值。

                         c.         把这个节点移到 close list 。

                         d.         停止,当你

                                         ◆     把终点加入到了 open list 中,此时路径已经找到了,或者

                                         ◆     查找终点失败,并且 open list 是空的,此时没有路径。

(3)         保存路径。从终点开始,每个方格沿着父节点移动直至起点,这就是你的路径。

3、代码:

逻辑层Node结点定义:
using UnityEngine;public enum GridState
{Empty,Block,
}
public class Node
{public GridState curState;public int X;public int Y;public int F;public int G;public int H;public Node parentNode;public Node(int x, int y){X = x;Y = y;ResetNode();}public void ResetNode(){curState = GridState.Empty;F = 0;G = 0;H = 0;parentNode = null;}public void CalculateValue(Node endNode){if (parentNode == null) return;//计算GG = GetPredictGValue(parentNode);//曼哈顿距离计算HH = Mathf.Abs(endNode.X - X) + Mathf.Abs(endNode.Y - Y);F = G + H;}public int GetPredictGValue(Node targetNode){int predictG = 0;//四连通if (targetNode.X == X || targetNode.Y == Y){predictG = targetNode.G + 10;}//八连通else{predictG = targetNode.G + 14;}return predictG;}}
寻路算法:
using System.Collections.Generic;public partial class PathFind
{private List<Node> openList;private List<Node> closeList;private Node[,] allNodeList;public void AStarInit(Node[,] allNodes){openList = new List<Node>();closeList = new List<Node>();allNodeList = allNodes;}public void FindRoad(Node startNode, Node endNode){openList.Add(startNode);LoopFindRoad(endNode);}private void LoopFindRoad(Node endNode){//找到终点或者不存在路径if (openList.Count == 0||openList.Contains(endNode)){return;}//找到F值最小的Node smallestFNode = null;for (int i = 0; i < openList.Count; i++){if (smallestFNode == null){smallestFNode = openList[i];continue;}if (openList[i].F<=smallestFNode.F){smallestFNode = openList[i];}}//获得八连通格子List<Node> eightAdjacent = GetRoundNode(smallestFNode);//更新代价for (int i = 0; i < eightAdjacent.Count; i++){//不在openList里面if (!openList.Contains(eightAdjacent[i])){eightAdjacent[i].parentNode = smallestFNode;eightAdjacent[i].CalculateValue(endNode);openList.Add(eightAdjacent[i]);}else{//判断是否需要更新F,G,Hif (eightAdjacent[i].GetPredictGValue(smallestFNode) <= eightAdjacent[i].G){eightAdjacent[i].parentNode = smallestFNode;eightAdjacent[i].CalculateValue(endNode);}}}//转移结点openList.Remove(smallestFNode);closeList.Add(smallestFNode);LoopFindRoad(endNode);}/// <summary>/// 获得八连通格子中可达到并且不在closeList中的格子/// </summary>/// <returns></returns>private List<Node> GetRoundNode(Node targetNode){int x = targetNode.X;int y = targetNode.Y;List<Node> tempList = new List<Node>();if (IsReachableNode(x, y + 1)) tempList.Add(allNodeList[x, y + 1]);if (IsReachableNode(x + 1, y + 1)) tempList.Add(allNodeList[x + 1, y + 1]);if (IsReachableNode(x + 1, y)) tempList.Add(allNodeList[x + 1, y]);if (IsReachableNode(x + 1, y - 1)) tempList.Add(allNodeList[x + 1, y - 1]);if (IsReachableNode(x, y - 1)) tempList.Add(allNodeList[x, y - 1]);if (IsReachableNode(x - 1, y - 1)) tempList.Add(allNodeList[x - 1, y - 1]);if (IsReachableNode(x - 1, y)) tempList.Add(allNodeList[x - 1, y]);if (IsReachableNode(x - 1, y + 1)) tempList.Add(allNodeList[x - 1, y + 1]);return tempList;}/// <summary>/// 判断格子是否可到达/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>private bool IsReachableNode(int x, int y){if (x >= allNodeList.GetLength(0) || x <= 0){return false;}if (y >= allNodeList.GetLength(1) || y <= 0){return false;}if (allNodeList[x, y].curState == GridState.Block){return false;}if (closeList.Contains(allNodeList[x, y])){return false;}return true;}
}

4、补充:

如果希望过障碍时,不允许他斜向过障碍,可以额外加个判断,原理很简单,对于8连通的角落点,判断角落点的4连通是否有障碍,如果有障碍就不算入可到达格子。

代码如下:

演示:

5、工程网盘链接:

通过网盘分享的文件:AStarDemo.unitypackage
链接: https://pan.baidu.com/s/1L_f1DIkqe9Oqm_dnFSSVew 提取码: 1212

http://www.lryc.cn/news/508205.html

相关文章:

  • 浏览器要求用户确认 Cookies Privacy(隐私相关内容)是基于隐私法规的要求,VUE 实现,html 代码
  • 如何设计高效的商品系统并提升扩展性:从架构到实践的全方位探索
  • 使用计算机创建一个虚拟世界
  • datasets笔记:两种数据集对象
  • 【ETCD】【Linearizable Read OR Serializable Read】ETCD 数据读取:强一致性 vs 高性能,选择最适合的读取模式
  • 【CSS in Depth 2 精译_089】15.2:CSS 过渡特效中的定时函数
  • 不常用命令指南
  • spring mvc | servlet :serviceImpl无法自动装配 UserMapper
  • STM32 HAL库之串口接收不定长字符
  • Pyqt6的tableWidget填充数据
  • ASP.NET Core - 依赖注入 自动批量注入
  • UVM 验证方法学之interface学习系列文章(十一)virtual interface 再续篇
  • 面试题整理5----进程、线程、协程区别及僵尸进程处理
  • OpenTK 中帧缓存的深度解析与应用实践
  • 第2节-Test Case如何调用Object Repository中的请求并关联参数
  • 【HarmonyOS NEXT】Web 组件的基础用法以及 H5 侧与原生侧的双向数据通讯
  • Android学习(六)-Kotlin编程语言-数据类与单例类
  • CV-OCR经典论文解读|An Empirical Study of Scaling Law for OCR/OCR 缩放定律的实证研究
  • 力扣274. H 指数
  • 挑战一个月基本掌握C++(第五天)了解运算符,循环,判断
  • Python的sklearn中的RandomForestRegressor使用详解
  • ReactPress 1.6.0:重塑博客体验,引领内容创新
  • 人脸生成3d模型 Era3D
  • kubeadm搭建k8s集群
  • centOS系统进程管理基础知识
  • STM32中ADC模数转换器
  • 初学stm32 --- 外部中断
  • wordpress调用指定分类ID下 相同标签的内容
  • SQL语法基础知识总结
  • css 实现呼吸灯效果