A星寻路原理:

略,网上可搜到
只简单说下F,G,H值
G:从起点A到当前点B的所耗费的移动距离。
H:此点到终点的移动距离(忽视障碍)。
F:F=G+H,用来寻找最优解。

通过理解A星寻路的原理可以设计出以下流程图:

Unity C#脚本实现流程图的代码:

此脚本挂在场景中任意空物体上即可实现效果,在Start()内可调整地图相关参数

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AStar : MonoBehaviour {//地图节点类型public enum NodeType    {moveable,   //可移动bar,        //障碍物boundary,   //边界aStarPath   //A星路径}//A星状态public enum AStarState{free,isInOpenList,isInCloseList}//pos<-->node 字典private Dictionary<Vector2, Node> PosNodeDict;//地图节点public class Node   {public Vector2 pos; public NodeType nodeType;public AStarState aStarState;public Node[] neighbourNodes;public Node parentNode=null;public float F=0;public float G=0;public float H = 0;}//地图初始化public Node[,] InitMap(int mapHeight,int mapLength){Node[,] nodes = new Node[mapHeight, mapLength];PosNodeDict = new Dictionary<Vector2, Node>();for (int i = 0; i < mapHeight; i++){for (int j = 0; j < mapLength; j++){nodes[i, j] = new Node();//边界判断if (i == 0){nodes[i, j].nodeType = NodeType.boundary;nodes[i, j].pos = new Vector2(j, i);}else if (j == 0){nodes[i, j].nodeType = NodeType.boundary;nodes[i, j].pos = new Vector2(j, i);}else if (i == mapHeight - 1){nodes[i, j].nodeType = NodeType.boundary;nodes[i, j].pos = new Vector2(j, i);}else if (j == mapLength - 1){nodes[i, j].nodeType = NodeType.boundary;nodes[i, j].pos = new Vector2(j, i);}else{nodes[i, j].nodeType = NodeType.moveable;nodes[i, j].pos = new Vector2(j, i);}//节点加入 坐标<-->节点 字典nodes[i, j].aStarState = AStarState.free;PosNodeDict.Add(new Vector2(j, i), nodes[i, j]);}}//初始化相邻坐标节点数组for (int i=0; i < mapHeight; i++){for(int j=0; j < mapLength; j++){nodes[i, j].neighbourNodes = new Node[8];Vector2 curNeighbVec2;//上curNeighbVec2 = new Vector2(j, i + 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[0] = PosNodeDict[curNeighbVec2];}//下curNeighbVec2 = new Vector2(j, i - 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[1] = PosNodeDict[curNeighbVec2];}//左curNeighbVec2 = new Vector2(j - 1, i);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[2] = PosNodeDict[curNeighbVec2];}//右curNeighbVec2 = new Vector2(j + 1, i);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[3] = PosNodeDict[curNeighbVec2];}//左上curNeighbVec2 = new Vector2(j - 1, i + 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[4] = PosNodeDict[curNeighbVec2];}//右上curNeighbVec2 = new Vector2(j + 1, i + 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[5] = PosNodeDict[curNeighbVec2];}//左下curNeighbVec2 = new Vector2(j - 1, i - 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[6] = PosNodeDict[curNeighbVec2];}//右下curNeighbVec2 = new Vector2(j + 1, i - 1);if (PosNodeDict.ContainsKey(curNeighbVec2)){nodes[i, j].neighbourNodes[7] = PosNodeDict[curNeighbVec2];}}}return nodes;}//设置障碍barpublic void AddBar(Vector2 barPos){if (PosNodeDict.ContainsKey(barPos)){print("bar added");PosNodeDict[barPos].nodeType = NodeType.bar;}}//地图具象化public void InstantiateMap(Node[,] nodes){for(int i = 0; i < nodes.GetLength(0); i++){for (int j = 0; j < nodes.GetLength(1); j++){GameObject curCube = GameObject.CreatePrimitive(PrimitiveType.Cube);curCube.transform.position = new Vector3(j, i, 0);if (nodes[i, j].nodeType == NodeType.boundary){print("set boundary");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.black);}else if (nodes[i, j].nodeType == NodeType.bar){print("set bar");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.red);}else if (nodes[i, j].nodeType == NodeType.aStarPath){print("set path");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.yellow);}}}}//地图具象化(并对Openlist,Closelist内节点上色)public void InstantiateMapBeta(Node[,] nodes){for (int i = 0; i < nodes.GetLength(0); i++){for (int j = 0; j < nodes.GetLength(1); j++){GameObject curCube = GameObject.CreatePrimitive(PrimitiveType.Cube);curCube.transform.position = new Vector3(j, i, 0);if (nodes[i, j].nodeType == NodeType.boundary){print("set boundary");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.black);}else if (nodes[i, j].nodeType == NodeType.bar){print("set bar");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.red);}else if (nodes[i, j].nodeType == NodeType.aStarPath){print("set path");curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.yellow);}else if(OpenList.Contains(nodes[i,j])){curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.green);}else if(CloseList.Contains(nodes[i,j])){curCube.GetComponent<Renderer>().material.SetColor("_Color", Color.blue);}}}}//寻路相关private List<Node> OpenList;private List<Node> CloseList;private Vector2 globalEndPos;//寻路入口public bool PathSearch(Node[,] nodes,Vector2 startPos,Vector2 endPos){//校验参数if (!PosNodeDict.ContainsKey(startPos) || !(PosNodeDict.ContainsKey(endPos))){print("invalid para");return false;}if(PosNodeDict[startPos].nodeType != NodeType.moveable||PosNodeDict[endPos].nodeType!=NodeType.moveable){print("invalid para");return false;}OpenList = new List<Node>();CloseList = new List<Node>();globalEndPos = endPos;//算法开始//起点为A//这里有点不直观,startPos的xy要倒过来引用nodes。感谢tuyou67评论指出。Node A = nodes[(int)startPos.y, (int)startPos.x];  A.G = 0;A.H = Mathf.Abs(globalEndPos.x - A.pos.x) + Mathf.Abs(globalEndPos.y - A.pos.y); //Vector2.Distance(A.pos, globalEndPos);A.F = A.G + A.H;A.parentNode = null;CloseList.Add(A);A.aStarState = AStarState.isInCloseList;do{//遍历OpenList,寻找F值最小的节点,设为Aif (OpenList.Count > 0){A = OpenList[0];}for (int i = 0; i < OpenList.Count; i++){if (OpenList[i].F < A.F){A = OpenList[i];}}Node path = AStarSearch(A);if (path != null){print("path found");do{path.nodeType = NodeType.aStarPath;if (path.parentNode == null){path = null;}else{path = path.parentNode;}} while (path!= null);return true;}OpenList.Remove(A);CloseList.Add(A);A.aStarState = AStarState.isInCloseList;//OpenList是否还有节点} while (OpenList.Count > 0);//无到达目的地的路径print("path not found");return false;}public Node AStarSearch(Node A){//遍历A的周边节点,当前处理节点为BNode B;for (int i = 0; i < A.neighbourNodes.Length; i++){if (A.neighbourNodes[i] == null){continue;}B = A.neighbourNodes[i];//是否是可移动节点if (B.nodeType != NodeType.moveable){continue;}//是否在开放列表中if (B.aStarState == AStarState.isInOpenList){//A到B的G值+A.G>B.Gfloat curG = Vector2.Distance(A.pos, B.pos);if (B.G > curG + A.G){//更新B的父节点为A,并相应更新B.G,B.HB.parentNode = A;B.G = curG + A.G;B.F = B.G + B.H;}continue;}else if(B.aStarState==AStarState.free){//更新B的父节点为A,并相应更新B.G; 计算B.F,B.H; B加入OpenListB.parentNode = A;B.G = Vector2.Distance(A.pos,B.pos)+A.G;B.H = Mathf.Abs(globalEndPos.x - B.pos.x) + Mathf.Abs(globalEndPos.y - B.pos.y); //Vector2.Distance(B.pos, globalEndPos);B.F = B.G + B.H;OpenList.Add(B);B.aStarState = AStarState.isInOpenList;//B.F==0if (B.H <Mathf.Epsilon){//B的所有父节点既是路径return B;}else{//继续遍历continue;}}else{continue;}}return null;}//程序入口// Use this for initializationvoid Start () {Node[,] nodes = InitMap(100, 100);AddBar(new Vector2(2, 2));AddBar(new Vector2(2, 3));AddBar(new Vector2(3, 2));AddBar(new Vector2(3, 3));AddBar(new Vector2(4, 4));AddBar(new Vector2(3, 4));AddBar(new Vector2(4, 3));AddBar(new Vector2(4, 5));AddBar(new Vector2(5, 4));AddBar(new Vector2(4, 6));AddBar(new Vector2(4, 7));AddBar(new Vector2(1, 7));AddBar(new Vector2(2, 7));AddBar(new Vector2(3, 7));PathSearch(nodes, new Vector2(1, 3), new Vector2(2,12));InstantiateMapBeta(nodes);}
}

效果图:

红色方块为障碍物,黑色方块为边界,灰色方块为空地,绿色方块为OpenList内节点,蓝色方块为CloseList内节点,黄色方块为路径。


————————————————————————————————
维护日志:
2017-8-31:更改标题,文章分类。
2018-8-2:Review,重写了代码,流程图,并更新了效果图。
2020-5-28:修改了startPos引用nodes的bug

Unity3DAI:寻路(1):A星寻路,在Unity上用C#代码实现。相关推荐

  1. 迷宫寻路(A星寻路算法)

    题目:假设我们有一个7×5大小的迷宫,如下图所示,绿色格子表示起点,红色的格子表示终点,中间的3个深灰色格子表示障碍物.请找到一条从起点到终点最短的路径. 解题思路:        需要引入两个集合和 ...

  2. Unity A星寻路

    使用A星寻路要把地图网格化,这是为了简化地图,图中阴影是障碍物 一些关键概念 开放列表(open list):记下所有被考虑用来寻找最短路径的格子 封闭列表(close list):记下已经搜索过的格 ...

  3. 地图信息,障碍判断以及寻路算法(A星算法,B星算法和蚁群算法等)

    一.广度优先遍历和深度优先遍历 在学习寻路算法之前,我们先来了解一下广度优先遍历和深度优先遍历. 什么是广度优先遍历? 广度优先遍历(breadth first search)是一个万能的算法. 广度 ...

  4. 【Android】基于A星寻路算法的简单迷宫应用

    简介 基于[漫画算法-小灰的算法之旅]上的A星寻路算法,开发的一个Demo.目前实现后退.重新载入.路径提示.地图刷新等功能.没有做太多的性能优化,算是深化对A星寻路算法的理解. 界面预览: 初始化: ...

  5. java a星寻路算法_用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...

  6. 如何实现A星寻路算法 Cocos2d-x 3 0 beta2

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本文实践 ...

  7. 如何实现A星寻路算法 Cocos2d-x 3.0 beta2

    本文实践自 Johann Fradj 的文章<How To Implement A* Pathfinding with Cocos2D Tutorial>,文中使用Cocos2D,我在这里 ...

  8. A星寻路算法(A* Search Algorithm)

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  9. 用Python从零复现A星寻路算法 | 手撕代码#1

    用Python从零复现A星寻路算法 |

最新文章

  1. Spring @SessionAttributes @ModelAttribute
  2. 写在我第一个虚幻程序之前
  3. 【问题解决】Processing库安装方法简介
  4. CF1016G. Appropriate Team(Pollard-pho,FWT,数论)
  5. primefaces_轻量级Web应用程序框架:PrimeFaces(JSF)+ Guice + MyBatis(第2部分)
  6. oracle实时分析,Oracle Exalytics 大幅提升实时分析洞察力
  7. 实现一个简单的前端水印
  8. 故障诊断:12cR2 Flex ASM 环境中节点启动失败的诊断和分析
  9. JavaScript学习(五十三)—借用构造方法继承
  10. 一等奖60万,首届“唱圆”杯AI翻译大赛报名中
  11. BI数据分析师入门项目
  12. 高数习题第八章总练习题(上)
  13. 赛事+内容IP齐发力,汽车之家打破Z世代次元壁
  14. 制作本地视频网站 苹果cms 超详细
  15. 产品 电信nb接口调用_【IoT】物联网NB-IoT之电信物联网开放平台对接流程浅析
  16. 金山词霸笔试题目笔记
  17. 华南农业大学C语言程序设计(实验六)
  18. 安卓流畅度测试方法二:FPS Meter测试安卓帧数
  19. echarts 仪表盘图展示百分比
  20. PAT 1003 Emergency(最短路(迪杰斯特拉||贝尔曼)最小边权下的最大点权)

热门文章

  1. 避免使用GroupByKey
  2. ES6语法---set
  3. H5新标签--语义化标签
  4. 破环计算机系统的案件量刑,破坏计算机信息系统罪如何定罪量刑
  5. 空间统计分析_CDA 数据分析师 Level 1 备考系列之推断性统计分析概述
  6. fastjson反序列化过滤字段属性_Fastjsonlt;=1.2.47反序列化漏洞源码分析及复现
  7. 台式计算机光标时不时跳动,解决方案:如何解决联想笔记本触摸板上的光标跳动?...
  8. python中的一些基础
  9. oracle的and怎么用,Oracle的BITAND的方法使用
  10. 人工智能可控核聚变量子计算机,中国终于实现了可控核聚变