使用Unity实现A*寻路算法
来源:互联网 发布:网络言论自由弊端事例 编辑:程序博客网 时间:2024/06/05 20:09
在寻路过程中有许多的影响因素,例如时间,能量,金钱,地形,距离的美好。对于起始节点与目标节点之间的每一条可行路径,都可以用代价的大小来描述。而A*算法的任务就是选取代价最小的那条路径
先介绍导航图(参考于Unity3D 人工智能编程精粹一书):
1.基于单元的导航图,寻路使以网格为单位进行的。如果单个正方形过大,网格很粗糙,那么很难得到好的路径,如果网格很精细,那么虽然会寻找到很好的路径,但这时需要存储和搜索大量的节点,对内存要求高,而且也很影响效率。
2.基于可视点导航图,一般由场景设计者在场景中手工放置一些路径点,然后由设计人员测试这些“路径点”之间的可视性
3.创建导航网格:导航网格将游戏场景中的可行走区域划分成凸多边形。导航网格表示出了可行走区域的真实几何关系,使一个非均匀网格。Unity3D自带的寻路系统就建立在导航网格的基础上。利用A*算法,可以找到路径所经过的那么多边形。如果直接把这些多边形的中心连接起来,就会得到从起始点到目标点的一条路径。下面用Unity3D来实现。
首先介绍A*寻路算法:
点击打开链接
下面是在Unity中实现的效果
绿色部分代表初始点,红色部分代表目标点,蓝色部分代表障碍物,灰色部分代表路径,白色部分代表整个虚拟网格
再给出他们的实现代码:
Ponit.cpp
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Point { public Point Parent { get; set; } //父节点 //F=G+H public int F { get; set; } public int G { get; set; } public int H { get; set; } //Position public int X { get; set; } public int Y { get; set; } //障碍物 public bool IsWall { get; set; } //非路径非障碍物,渲染成白色 public bool IsWhite { get; set; } public Point(int x,int y , Point parent = null) { this.X = x; this.Y = y; this.Parent = parent; IsWall = false; IsWhite = true; } //更新父节点 public void UpdateParent(Point parent,int g) { this.Parent = parent; this.G = g; F = G + H; }}
AStar.cpp
using System.Collections;using System.Collections.Generic;using UnityEngine;public class AStar : MonoBehaviour { private const int mapWith = 8; private const int mapHeight = 8; private Point[,] map = new Point[mapWith, mapHeight];// Use this for initializationvoid Start () { InitMap(); //虚拟化地图 //定义初试点和目的点 Point start = map[2,3]; Point end = map[7, 4]; //寻找路径 FindPath(start, end); //显示路径 ShowPath(start,end); //List<Point> l= GetSurroundPoints(map[0, 0]); //foreach(Point p in l) //{ // Debug.Log(p.X + "-" + p.Y); //}} private void ShowPath(Point start,Point end) { Point temp = end; //从目的点倒回出发点来显示路径 while (true) { //Debug.Log(temp.X + "," + temp.Y); Color c = Color.gray; if (temp == start) { c = Color.green; }else if (temp == end) { c = Color.red; } CreateCube(temp.X, temp.Y, c); temp.IsWhite = false; if (temp.Parent == null) break; temp = temp.Parent; } for (int x = 0; x < mapWith; x++) { for (int y = 0; y < mapHeight; y++) { if (map[x, y].IsWall) { CreateCube(x, y, Color.blue); } if (map[x, y].IsWhite==true ) { CreateCube(x, y, Color.white); } } } } private void CreateCube(int x,int y,Color color) { GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube); go.transform.position = new Vector3(x, y, 0); go.GetComponent<Renderer>().material.color = color; } private void InitMap() { for(int x = 0; x < mapWith; x++) { for(int y = 0; y < mapHeight; y++) { map[x, y] = new Point(x,y); } } map[4, 2].IsWall = true; map[4, 3].IsWall = true; map[4, 4].IsWall = true; map[4, 5].IsWall = true; map[4, 6].IsWall = true; map[4, 2].IsWhite = false; map[4, 3].IsWhite = false; map[4, 4].IsWhite = false; map[4, 5].IsWhite = false; map[4, 6].IsWhite = false; } private void FindPath(Point start,Point end) { List<Point> openList = new List<Point>();//openList表,等待考察的节点的优先级队列 List<Point> closeList = new List<Point>();//已经考察过,无须再考察的节点列表 openList.Add(start); while (openList.Count > 0) { Point point = FindMinFOfPoint(openList); //在openList表中选择F最小的值加入closeList表中 openList.Remove(point); closeList.Add(point); List<Point> surroundPoints = GetSurroundPoints(point); //寻找周围点 PointsFilter(surroundPoints, closeList); //过滤掉close表中已有的节点 foreach(Point surroundPoint in surroundPoints) { if (openList.IndexOf(surroundPoint) > -1) //如果在openList已经存在,比较 { int nowG =(int) CalcG(surroundPoint, point); if(nowG< surroundPoint.G) { surroundPoint.UpdateParent(point,nowG); } } else { surroundPoint.Parent = point; CalcF(surroundPoint, end); openList.Add(surroundPoint); } } //判断一下 if (openList.IndexOf(end) > -1) //如果到达了目的地,break { break; } } } private void PointsFilter(List<Point> src,List<Point> closeList) { foreach(Point p in closeList) { if (src.IndexOf(p) > -1) { src.Remove(p); } } } private List<Point> GetSurroundPoints(Point point) { Point up = null, down = null, left = null, right = null; Point lu = null, ru = null, ld = null, rd = null; if (point.Y < mapHeight- 1) { up = map[point.X, point.Y + 1]; } if (point.Y > 0) { down = map[point.X, point.Y - 1]; } if (point.X > 0) { left = map[point.X - 1, point.Y]; } if(point.X <mapWith-1) { right = map[point.X + 1, point.Y]; } if (up != null && left != null) { lu = map[point.X - 1, point.Y + 1]; } if (up != null && right != null) { ru = map[point.X + 1, point.Y + 1]; } if (down != null && left != null) { ld = map[point.X - 1, point.Y - 1]; } if (down != null && right != null) { rd = map[point.X + 1, point.Y - 1]; } List<Point> list = new List<Point>(); if (down != null && down.IsWall == false) { list.Add(down); } if (up != null && up.IsWall == false) { list.Add(up); } if (left != null && left.IsWall == false) { list.Add(left); } if (right != null && right.IsWall == false) { list.Add(right); } if (lu != null && lu.IsWall == false && left.IsWall == false && up.IsWall == false) { list.Add(lu); } if (ld != null && ld.IsWall == false && left.IsWall == false && down.IsWall == false) { list.Add(ld); } if (ru != null && ru.IsWall == false && right.IsWall == false && up.IsWall == false) { list.Add(ru); } if (rd != null && rd.IsWall == false && right.IsWall == false && down.IsWall == false) { list.Add(rd); } return list; } private Point FindMinFOfPoint(List<Point> openList) { int f = int.MaxValue; Point temp = null; foreach(Point p in openList) { if (p.F < f) { temp = p; f = p.F; } } return temp; } private float CalcG(Point now,Point parent) { return Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(parent.X, parent.Y)) + parent.G; } private void CalcF(Point now,Point end) { //F = G + H int h = Mathf.Abs(end.X - now.X) + Mathf.Abs(end.Y - now.Y); int g = 0; if (now.Parent == null) { g = 0; } else { g=(int)Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(now.Parent.X, now.Parent.Y)) + now.Parent.G; } int f = g + h; now.F = f; now.G = g; now.H = h; }}
阅读全文
1 0
- 使用Unity实现A*寻路算法
- Unity A*算法实现
- Unity中利用A*算法实现简单寻路
- Unity A*寻路算法
- unity 接入A*寻路算法总结
- [Unity] A-Star(A星)寻路算法
- A* Pathfinding Project (Unity A*寻路插件) 使用教程
- A* Pathfinding Project (Unity A*寻路插件) 使用教程
- A* Pathfinding Project (Unity A*寻路插件) 使用教程
- Unity Game Programming AI(5)A Star寻路算法
- Unity A*寻路三个简单实用的算法
- Unity A*寻路三个简单实用的算法
- Unity A*寻路算法(人物移动AI)
- 如何在使用Cocos2D中实现A星(A*)寻路算法
- IOS 如何在使用Cocos2D中实现A星(A*)寻路算法
- unity中实现A*算法的一些问题
- Unity A*寻路详解
- JS中实现A*算法寻路
- 一条hang住数据库的SQL的分析
- 八.SpringBoot集成实例系列-持久化jpa
- 如何安装WindowsBuilder插件
- 高德地图Key添加之SHA1
- AJAX之利用时间戳解决缓存问题
- 使用Unity实现A*寻路算法
- Linux如何查看YUM的安装目录
- win10 安装VMware Workstation Pro 14出现无法连接 MKS: 套接字连接尝试次数太多;正在放弃.
- Android开发中如何使用抓包工具Fiddler更改后台接口数据
- 项目部署到阿里云登录页面图形验证码乱码问题的解决办法
- 文件上传进度条显示
- Log4j2中RollingFile的文件滚动更新机制 一、什么是RollingFile RollingFileAppender是Log4j2中的一种能够实现日志文件滚动更新(rollover)的
- hdoj 1005 number sequence(找规律)
- 众数