演示:

我们知道Unity中的Navigation只能实现3D场景的寻路,不能实现2D的寻路,常见的寻路算法有很多种,其中A星是项目中最常用的寻路方法。在项目中用到了A星,就简单总结一下吧。

原理:

最通俗的原理就是寻找周围的点。选出一个到终点最近的点,再从选出的点为起点寻找下一个点,直到到达目标点。

实现:

如何选出最近的点呢,我们就会利用曼哈顿街区算法公式寻找下一个点。

如下图:我们以黄色为起点,黄色的点周围有八个可以移动的点,移动的距离对角移动为1.4,直线移动为1。

我们用f来代表寻路的总代价,g代表从开始点到下一个点的距离,h(此处用到麦哈顿街区算法)为从下一个点到目标点的距离。则f=g+h

因此我们的格子类就基本完成了;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 格子的类型
/// </summary>
public enum E_Node_Type {Walk,Stop}/// <summary>
/// 格子类
/// </summary>
public class AStarNode
{//格子的坐标public int x;public int y;//寻路消耗public float f;//起点距离public float g;//终点距离public float h;//父对象public AStarNode father;public E_Node_Type type;public AStarNode( int x,int y,E_Node_Type type){this.x = x;this.y = y;this.type = type;}
}

接下来写寻路的控制器,经过分析,应该记录开始点周围的每一个点,经过计算后看看他是否是最近的点。这里我们就需要两个列表,一个列表记录格子周围的点。另一个列表我们要记录最近路径上的格子。另外我们还要一个二维数组来记录地图的信息。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// A星管理器
/// </summary>
public class AStarMgr : MonoBehaviour
{public static AStarMgr Instance;//地图的宽高private int mapW;private int mapeH;//地图相关的所有的格子容器public AStarNode[,] nodes;//开启列表private List<AStarNode> openList=new List<AStarNode>();//关闭列表private List<AStarNode> closeList=new List<AStarNode>();private void Awake(){Instance = this;}/// <summary>/// 初始化地图信息/// </summary>/// <param name="w"></param>/// <param name="h"></param>public void InItMapInfo(int w,int h){this.mapeH = h;this.mapW = w;nodes = new AStarNode[w,h];for (int i = 0; i < w; i++){for (int j = 0; j < h; j++){AStarNode node = new AStarNode(i, j, Random.Range(0, 100) < 20 ? E_Node_Type.Stop : E_Node_Type.Walk);nodes[i, j] = node;}}}/// <summary>/// 寻路的方法/// </summary>/// <param name="startPos"></param>/// <param name="endPos"></param>/// <returns></returns>public List<AStarNode>FindPath(Vector2 startPos,Vector2 endPos){//判断起始点是不是在地图的范围内if (startPos.x < 0 || startPos.x >= mapW|| startPos.y < 0 || startPos.y >= mapeH|| endPos.x < 0 || endPos.x >= mapW|| endPos.y < 0 || endPos.y >= mapeH)return null;//判断起始点是不是不能通行的点AStarNode start = nodes[(int)startPos.x, (int)startPos.y];AStarNode end = nodes[(int)endPos.x, (int)endPos.y];if (start.type == E_Node_Type.Stop || end.type == E_Node_Type.Stop)return null;closeList.Clear();openList.Clear();//开始点放入关闭列表中start.father = null;start.f = 0;start.g = 0;start.h = 0;closeList.Add(start);while (true){//周围的点FindNearlyToOpenList(start.x - 1, start.y - 1, 1.4f, start, end);FindNearlyToOpenList(start.x, start.y - 1, 1.4f, start, end);FindNearlyToOpenList(start.x + 1, start.y - 1, 1.4f, start, end);FindNearlyToOpenList(start.x - 1, start.y, 1.4f, start, end);FindNearlyToOpenList(start.x + 1, start.y, 1.4f, start, end);FindNearlyToOpenList(start.x - 1, start.y + 1, 1.4f, start, end);FindNearlyToOpenList(start.x, start.y + 1, 1.4f, start, end);FindNearlyToOpenList(start.x + 1, start.y + 1, 1.4f, start, end);if (openList.Count == 0)return null;//排序选出最小的点openList.Sort(SortOpenList);//放入关闭列表,然后从开启列表中移除closeList.Add(openList[0]);//找到这个点,进行下一次寻路start = openList[0];openList.RemoveAt(0);if (start == end){//结束List<AStarNode> path = new List<AStarNode>();path.Add(end);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;elsereturn -1;}/// <summary>/// 临近的点放入开启列表/// </summary>/// <param name="x"></param>/// <param name="y"></param>private void FindNearlyToOpenList(int x,int y,float g,AStarNode father, AStarNode end){if (x < 0 || x >= mapW || y < 0 || y >= mapeH)return;AStarNode node = nodes[x, y];if (node == null||node.type==E_Node_Type.Stop||closeList.Contains(node)||openList.Contains(node))return;//计算f值 f=g+h;node.father = father;node.g = father.g + g;node.h = Mathf.Abs(end.x - node.x) + Mathf.Abs(end.y - node.y);node.f = node.g + node.h;openList.Add(node);}}

以上的代码就完成了A星算法的核心内容。下边为测试代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TestAStar : MonoBehaviour
{public int beginX = -3;public int beginY = 5;public int offsetX = 2;public int offsetY = 2;public int mapW = 5;public int mapH = 5;private Vector2 beginPos = Vector2.right * -1;private Vector2 endPos = Vector2.right * -1;public Material red;public Material yellow;private Dictionary<string, GameObject> cubes = new Dictionary<string, GameObject>();void Start(){AStarMgr.Instance.InItMapInfo(mapW, mapW);for (int i = 0; i < mapW; i++){for (int j = 0; j < mapH; j++){GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);obj.transform.position = new Vector3(beginX + i * offsetX, beginY + j * offsetY, 0);obj.name = i + "_" + j;cubes.Add(obj.name, obj);AStarNode node = AStarMgr.Instance.nodes[i, j];if (node.type == E_Node_Type.Stop){obj.GetComponent<MeshRenderer>().material = red;}}}}// Update is called once per framevoid Update(){if (Input.GetMouseButtonDown(0)){RaycastHit hit;Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out hit, 1000)){if (beginPos == Vector2.right * -1){string[] strs = hit.collider.gameObject.name.Split('_');beginPos = new Vector2(int.Parse(strs[0]), int.Parse(strs[1]));hit.collider.gameObject.GetComponent<MeshRenderer>().material = yellow;}else{string[] strs = hit.collider.gameObject.name.Split('_');endPos = new Vector2(int.Parse(strs[0]), int.Parse(strs[1]));Debug.Log(endPos);List<AStarNode> list = AStarMgr.Instance.FindPath(beginPos, endPos);Debug.Log(list.Count);if (list != null){for (int i = 0; i < list.Count; i++){Debug.Log(list[i]);cubes[list[i].x + "_" + list[i].y].GetComponent<MeshRenderer>().material = yellow;}}}}}}
}

以上为A星寻路算法的核心理念,在用到商业项目中肯定要对算法进行封装。那下边就介绍一个已经封装完善的A星算法插件:

A* Pathfinding Project

下载免费版:点击更多信息-点击download就可以下载免费版。

使用方法看这个视频吧:

Unity 2D AI自动寻路功能 [风农译制]_哔哩哔哩_bilibilihttps://www.youtube.com/watch?v=jvtFUfJ6CP8利用A* 寻路项目做的unity自动寻路。涉及到较多脚本编写,有不明白的部分可以看我之前的脚本教程。A* Pathfinding 项目地址: https://arongranberg.com/astar/https://www.bilibili.com/video/BV1D4411N7FZ

Unity A星(A Star/A*)寻路算法相关推荐

  1. 盘点即时战略游戏中高实用性寻路算法

    编者按:在即时战略(RTS)游戏中,寻路系统可谓其核心要素之一,但它的算法也是较难攻克的内容之一.在这篇文章中,来自iSamurai工作室的伍一峰为广大游戏开发者带来了他对即时战略游戏寻路算法的深入思 ...

  2. 即时战略游戏中实用的寻路算法分享

    http://www.gameres.com/340777.html GameRes游资网授权发布,文 / 伍一峰 RTS中的寻路系统一般需要满足有以下几个条件: 1. 效率高,因为rts普遍地图大, ...

  3. a 寻路算法 java_A*(也叫A star, A星)寻路算法Java版 | 学步园

    寻路 首先要理解什么是A*寻路算法,可以参考这三篇文章: 下面为测试地图,0表示可以通行,1表示障碍物: 要从点(5, 1)到点(5, 5),通过A*寻路算法找到以路径为@所示: 在代码中可以修改障碍 ...

  4. a 寻路算法 java_A*(也叫A star, A星)寻路算法Java版

    寻路算法有非常多种,A*寻路算法被公觉得最好的寻路算法. 首先要理解什么是A*寻路算法,能够參考这三篇文章: 以下为測试地图.0表示能够通行,1表示障碍物: 要从点(5, 1)到点(5, 5).通过A ...

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

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

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

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

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

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

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

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

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

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

最新文章

  1. python 编码规范 PEP8整理
  2. 向上滚动tabBar隐藏向下显示
  3. UNITY录制视屏解决方案 - ShareREC For Unity3D
  4. Spring MVC 实现原理
  5. c++(和opencv)如何把局部变量变成全局变量的功能
  6. 鸟哥的Linux私房菜(基础篇)-第零章、计算机概论(零.3)
  7. synchronized修饰静态方法与实例方法
  8. QT的QThread类的使用
  9. Spring 5的最终功能发行版即将来临
  10. 解决 fatal: unable to access xxx: Encountered end of
  11. 物联网应用技术和计算机应用技术哪个更好,2020物联网应用技术专业选什么大学好?...
  12. 【内网安全】基础知识:工作组、域和权限分配
  13. 将Python代码打包成Windows 10的可执行文件
  14. LGWR waits for event ‘DLM cross inst call completion’ 故障排除
  15. XPS如何在线转Word格式
  16. 4.Python数据结构与算法分析课后习题__chapter4
  17. 可变参数和Steam流的基本使用
  18. 牛顿法与牛顿下山法(切线法)
  19. 直播回顾 | 一起来get 电商风控实操知识点
  20. 系统调用中断(EINTR)与SIGCHLD信号的处理

热门文章

  1. 在计算机上收回光驱快捷键,如何在Windows中使用键盘快捷键打开光驱
  2. 警惕 频繁染发伤肾脏
  3. 4搬砖和抱你,我该如何选择?
  4. Comparator比较器
  5. 解析las文件_LAS格式的解析与转换
  6. 关于vue过滤器的原理解析
  7. 00003 不思议迷宫.0009.10:Bug之二:免称号锻造、升级装备,合成卷轴
  8. linux shell tomcat 一键重启
  9. java filter response_ZuulFilter中设置Response的原理。
  10. 什么是服务熔断?什么是服务降级?