unityA星寻路算法基础原理

article/2025/3/3 5:00:58

@作者: 风不停息丶
在这里插入图片描述

文章目录

  • 🧑‍💻A星寻路简介
  • 👉代码基础架构
  • 👍代码实现
    • 格子类
    • 寻路管理类
    • 效果
  • 结尾总结


🧑‍💻A星寻路简介

A*寻路就是用来计算玩家行进路径的,通过它可以计算出避开阻挡的最短路径
A星寻路算法的基本原理就是不停的找自己周围的点,选出一个新的点作为起点再循环的找
主要是应用于2D游戏上面的寻路AI算法

  • A星寻路原理

1.寻路消耗公式: f(寻路消耗) = g(离起点的距离) + h(终点的距离)
2.开启列表
3.关闭列表
4.格子对象的父对象

在这里插入图片描述

开启列表:每次从新的点找周围的点时,如果周围的点已经在开启列表或者关闭列表中了,我们就不用去管它
关闭列表:每次往关闭列表中放点时,我们都应该判断这个点是不是和终点一样,如果是一样证明路径找完了,如果不一样,继续找

在这里插入图片描述

👉代码基础架构

在这里插入图片描述


👍代码实现

格子类

/// <summary>
/// 格子类型枚举
/// </summary>
public enum E_AStar_Type{Walk,//可行走Stop//阻挡物
}/// <summary>
/// A星寻路 格子类
/// </summary>
public class AStarNode
{//格子对象坐标 行列(x,y)public int x;public int y;//寻路消耗public float f;//离起点的距离public float g;//离终点的距离public float h;//父对象public AStarNode father;//格子类型public E_AStar_Type type;/// <summary>/// 格子类型构造函数 /// </summary>/// <param name="x">行</param>/// <param name="y">列</param>/// <param name="type">格子类型</param>public AStarNode(int x,int y,E_AStar_Type type){this.x = x;this.y = y;this.type = type;}
}

寻路管理类

/// <summary>
/// A星寻路管理类
/// </summary>
public class AStarMgr
{//私有单例private static AStarMgr instance;//公有属性public static AStarMgr Instance{get{//保证唯一性 如果为空new一个if (instance == null){instance = new AStarMgr();}return instance;}}//地图的宽高private int mapW;private int mapH;//地图相关所有的格子对象容器public AStarNode[,] nodes;//创建开启列表private List<AStarNode> openList = new List<AStarNode>();//创建关闭列表private List<AStarNode> closeList = new List<AStarNode>();/// <summary>/// 初始化地图/// </summary>/// <param name="w">宽</param>/// <param name="h">高</param>public void InitMapInfo(int w ,int h){//记录宽高 范围this.mapW = w;this.mapH = h;//初始化AStarNodenodes = new AStarNode[w, h];//创建生成地图for (int r = 0; r < w - 1; r++){for (int c = 0; c < h - 1; c++){//随机生成阻挡格子 百分之二十概率 //注意:真正的项目中 这些阻挡信息应该是从地图配置文件中读取出来的 不应该是随机的AStarNode node = new AStarNode(r, c, Random.Range(0, 100) < 20 ? E_AStar_Type.Stop : E_AStar_Type.Walk);//赋值nodes[r, c] = node;}}}/// <summary>/// 寻路方法 提供给外部使用/// </summary>/// <param name="startPos">起点</param>/// <param name="endPos">终点</param>/// <returns></returns>public List<AStarNode> FindPath(Vector2 startPos,Vector2 endPos){//实际项目中传入的点往往是坐标系中的位置**********//这里省略换算的步骤直接认为它是传进来的格子坐标***********//有些是float类型小数 需要和世界坐标进行转换***********//1.首先要在地图范围内 x y不能越界if (startPos.x<0||startPos.x>=mapW||startPos.y<0||startPos.y>=mapH||endPos.x < 0 || endPos.x >= mapW || endPos.y < 0 || endPos.y >= mapH){Debug.Log("开始或者结束点在地图格子范围外");return null;}//2.要不是阻挡的 先取出 开始 结束 点//原Vector2 float类型需转换为世界坐标(老师没教) 先直接强制转换为intAStarNode start = nodes[(int)startPos.x, (int)startPos.y];AStarNode end = nodes[(int)endPos.x, (int)endPos.y];//判断类型是否为Walk类型if (start.type == E_AStar_Type.Stop || end.type == E_AStar_Type.Stop){Debug.Log("开始或结束点是阻挡");return null;}//得到起点和终点 对应的格子//需清空上一次相关的数据 避免他们影响 这一次的寻路计算//清空关闭和开启列表closeList.Clear();openList.Clear();//开始点信息清空start.father = null;start.f = 0;start.g = 0;start.h = 0;//把开始点 放入关闭列表中closeList.Add(start);while (true){//从起点开始 找周围的点 并放入开启列表中//左上 x-1 y-1FindNearlyNodeToOpenList(start.x - 1, start.y - 1, 1.4f, start, end);//上   x   y-1FindNearlyNodeToOpenList(start.x, start.y - 1, 1f, start, end);//右上 x+1 y-1FindNearlyNodeToOpenList(start.x + 1, start.y - 1, 1.4f, start, end);//左   x-1 yFindNearlyNodeToOpenList(start.x - 1, start.y, 1f, start, end);//右   x+1 yFindNearlyNodeToOpenList(start.x + 1, start.y, 1f, start, end);//左下 x-1 y+1FindNearlyNodeToOpenList(start.x - 1, start.y + 1, 1.4f, start, end);//下   x   y+1FindNearlyNodeToOpenList(start.x, start.y + 1, 1f, start, end);//右下 x+1 y+1FindNearlyNodeToOpenList(start.x + 1, start.y + 1, 1.4f, start, end);//死路判断开启列表为空都还没有找到终点就认为是死路if (openList.Count == 0){Debug.Log("死路");return null;}//选出开启列表中寻路消耗最小的点 列表排序.SortopenList.Sort(SortOpenList);//放入关闭列表中 然后再从 开启列表中移除closeList.Add(openList[0]);//找得这个点又编程新的起点进行下一次寻路计算了start = openList[0];//每次获取开启列表的第一个值openList.RemoveAt(0);//开启列表中移除//如果这个点已经是终点 那么得到最终结果返回出去//如果这个点 不是终点 那么继续寻路if (start == end){//找完了 已经找到路径 最终路径List<AStarNode> path = new List<AStarNode>();path.Add(start);//回溯每个点while (end.father != null){path.Add(end.father);end = end.father;}//列表反转path.Reverse();return path;}}}/// <summary>/// 排序函数/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>private int SortOpenList(AStarNode a,AStarNode b){if (a.f > b.f){return 1;}else if (a.f == b.f){return 1;}else{return -1;}}/// <summary>/// 把临近的点放入开启列表中的函数/// </summary>/// <param name="x">行</param>/// <param name="y">列</param>/// <param name="g">方向格子 离起点距离</param>/// <param name="father">父对象</param>/// <param name="end">终点位置</param>private void FindNearlyNodeToOpenList(int x,int y,float g,AStarNode father,AStarNode end){//边界判断if (x<0||x>=mapW||y<0||y>=mapH){return;}//在边界范围内 再去取点 AStarNode node = nodes[x, y];//判断这些点 是否为空 是否是阻挡  是否在开启或者关闭列表 如果都不是 才放入开启列表中if (node == null || node.type == E_AStar_Type.Stop||closeList.Contains(node)||openList.Contains(node))//.Contains包含的意思{return;}//计算f值 寻路消耗//f = g + h;//记录父对象node.father = father;//计算g 现在到起点的距离 = 父亲离起点的距离 + 现在离父亲的距离node.g = father.g + g;//计算h 离终点的距离 曼哈顿算法node.h = Mathf.Abs(end.x - node.x) + Mathf.Abs(end.y - node.y);node.f = node.g + node.h;//如果通过了上面的合法验证就存到开启列表中openList.Add(node);//保存}
}

效果

在这里插入图片描述


结尾总结

这就是A星寻路的基础算法了,优化算法老师还没教,看到这篇文章的同志们可以点个赞👍支持一下,谢谢!
在这里插入图片描述


http://chatgpt.dhexx.cn/article/mloGcIkm.shtml

相关文章

【YOLO系列】YOLO.v1算法原理详解

YOLO(You Only Look Once)系列算法原理 前言 &#xff1a;详细介绍了yolo系列目标检测算法的原理和发展过程。 系列&#xff1a; 【YOLO系列】YOLO.v1算法原理详解 【YOLO系列】YOLO.v2算法原理详解 【YOLO系列】YOLO.v3算法原理详解 【YOLO系列】YOLO.v4 & YOLO.v5算法原…

A*算法原理与实现

前言 A*算法最初发表于1968年&#xff0c;由Stanford研究院的Peter Hart, Nils Nilsson以及Bertram Raphael发表。它可以被认为是Dijkstra算法的扩展。 由于借助启发函数的引导&#xff0c;A*算法通常拥有更好的性能。 一、 A*吸取了Dijkstra 算法中的cost_so_far&#xff0c;为…

激光SLAM之NDT算法(1)算法原理

/在激光SLAM之NDT算法&#xff08;2&#xff09;-建图中我会给出实测可用的建图代码,并予以解释代码结构,这里就先讲讲原理吧!!!/ 无人车激光SLAM系统简单可以分为建图和定位两部分&#xff0c;无人车的定位问题&#xff0c;实际上就是要找出无人车当前在地图的那个位置&#x…

A*算法的原理及应用

A*算法的原理 A* 算法是一种高效的启发式搜索算法&#xff0c;在二维的栅格地图上寻路效果好&#xff0c;它通过估算节点的代价评估函数值并作为节点的综合优先级&#xff0c;当选择下一个需要遍历的节点时&#xff0c;再选取综合优先级最高的节点&#xff0c;逐步地找到最优路…

Bresenham 画圆算法原理

文章目录 前言Bresenham 画圆算法原理两个近似构造判别式圆与网格点的关系关系由来关系含义p i p_i pi​ 递推画圆程序伪码圆与网格点的关系图示前言 首先简要介绍一下生成圆的方法: 直接利用圆的方程生成圆利用圆的对称性生成圆方法一由于会涉及到浮点运算等因素,不采取该方…

Js中读取、移除属性及隐藏组件方法研究

添加、移除组件属性方法: $(".class名").attr("属性名","属性值");//设置指定属性 $(".class名").attr("属性名");//读取指定属性值 or document.getElementById("id值").getAttribute("属性名…

js获取属性值,自定义属性,修改移除属性值

补充&#xff1a;由于不清楚一些属性是内置属性还是自定义属性 所以h5规定 自定义属性使用date-开头作为属性并赋值 案例1: <body><div date-index"1"></div> </body> <script>var div document.querySelector(div);console.log(div…

获取/移除属性值

1.获取属性值&#xff1a; element.属性 获取属性值 element.getAttribute&#xff08;‘属性’&#xff09;&#xff1b; 2.区别&#xff1a; element.属性 获取内置属性值&#xff08;元素本身自带的属性&#xff09; element.getAttribute&#xff08;‘属性’&#xff09;&…

JavaScript移除对象中不必要的属性

Thinking系列&#xff0c;旨在利用10分钟的时间传达一种可落地的编程思想。 业务开发中&#xff0c;我们经常会遇到&#xff1a;基于后端返回接口数据&#xff0c;前端保存到对象 Object 中&#xff0c;前端开发过程中为了一些场景的便利性&#xff0c;需要在该对象中增加相应的…

js移除属性

一、效果 代码 <style>div{width:100px;height: 100px;background-color: red;}.clsP{background-color: #00FF00;}</style><body><input type"button" value"移除属性" id"btn" /><div id"dv" score&q…

合天网安实验室CTF-解密100-Funny Crypto

合天网安实验室CTF-解密100-Funny Crypto 题目描述 tgbnjuy 8ujko9 5rfgy6 相关附件 题目链接 参考解题步骤 字母被围起来的字母图示颜色tgbnjuyh红8ujko9i绿5rfgy6t蓝 提交flag&#xff1a;hit

数字取证之Autopsy ——合天网安实验室学习笔记

实验链接 Autopsy Forensic Browser 是数字取证工具-The Sleuth Kit&#xff08;TSK&#xff09;的图形界面&#xff0c;用于对文件系统和卷进行取证。通过本实验学习文件系统取证的思想与方法&#xff0c;掌握Autopsy的使用。 链接&#xff1a;http://www.hetianlab.com/exp…

【合天网安】CONN.ASP暴库漏洞实验

0x01预备知识 1、概念&#xff1a; 相对路径和绝对路径 绝对路径&#xff1a;例如D&#xff1a;/test/test.mdb 相对路径&#xff1a;例如/test/test.mdb 2、%5C暴库 简单点说&#xff0c;就是在打开页面的时候把网页中的/换成%5C&#xff0c;然后提交就可以得到数据库地址…

【合天网安】FCKeditor 2.4.3文件上传漏洞

【合天网安实验室】FCKeditor 2.4.3文件上传漏洞 编辑器漏洞 常见的文本编辑器有FCKeditor、Ewebeditor、UEditor、KindEditor、XHeditor等&#xff0c;它们包含的功能类似&#xff0c;如图片上传、视频上传、远程下载等。使用这类编辑器减少了程序开发的时间&#xff0c;但也…

摩尔斯电码和栅栏密码 ——合天网安实验室学习笔记

实验链接 通过学习本实验理解摩尔斯电码和栅栏密码的编码解码过程&#xff1b;掌握编写摩尔斯电码的编码解码程序和编写多功能栅栏密码的编码解码程序。 链接&#xff1a;http://www.hetianlab.com/expc.do?ce64d3e661-ebbb-41fd-a220-a17d608f994e 实验简介 实验所属系列…

【合天网安】DoraBox之文件包含及任意文件读取漏洞

【合天网安实验室】DoraBox之文件包含及任意文件读取漏洞 目的&#xff1a; 过DoraBox靶场系列练习&#xff0c;学习任意文件包含、目录限制文件包含及任意文件读取漏洞的利用过程。 实验过程&#xff1a; 1.确保Apache、MySQL服务正常开启 2、查看.txt文本内容 3.使用includ…

合天网安实验室-sql注入实验一

根据指导书我们要先在实验机进入这个网址http://10.1.1.11:81 进入之后会看到三个实例。 实例一 根据指导书的提示来做这一题。后面两个实例也要看这个指导书。 先判断是否存在注入 方法一 在参数后面加上单引号,比如: http://xxx/abc.php?id1’ 如果页面返回错误&#xff…

合天网安《Weekly CTF》第四周

Check your source code 题目介绍 打开靶机&#xff0c;进步网站&#xff0c;是一个登陆框 首先&#xff0c;根据题名的提示&#xff0c;f12&#xff0c;发现存在source.txt 打开source.txt&#xff0c;出现源码 对源码进行分析 <?php $flag "XXXXXXXXXXXX"…

计算机取证之Xplico ——合天网安实验室学习笔记

实验链接 Xplico是一款开源的网络取证分析工具&#xff0c;其分析与呈现的能力非常强大。Xplico可以捕获Internet网络应用层流量&#xff0c;通过流量解析&#xff0c;解析出网络包中的各种应用数据&#xff0c;还原网络数据发送现场。通过本实验学习掌握Xplico使用方法&#…

合天网安实验室CTF-Exp200-Come on,Exploit me!

合天网安实验室CTF-Exp200-Come on,Exploit me! 题目描述 Audrey Tang. ⊙.⊙ 我只能说到这儿了 相关附件 exp200 题目链接 参考解题步骤 1、下载附件先用VSCode打开看看 换个行看看 通过and换行有68行 2、根据题目描述猜测   如果没有接触过perl语言看到这些文本应该…