A*寻路相信很多人都听说过,也是比较基本的一种算法,具体概念我就不多说了,网上查找一下一大堆,我直接贴上我的A*应用方法,以下是地图:
接下来是地图数组:
using UnityEngine; using System.Collections; public static class MapsArray { public static int[,] MazeItem = new int[15, 10] //初始化迷宫 { {1,1,1,1,1,1,1,1,1,1}, {1,0,1,1,1,0,0,0,1,1}, {1,0,0,1,1,0,1,0,1,1}, {1,0,0,0,0,0,1,0,1,1}, {1,1,0,1,0,1,1,0,1,1}, {1,1,0,1,0,0,0,0,1,1}, {1,0,0,0,1,1,1,0,1,1}, {1,1,0,0,0,0,0,0,1,1}, {1,1,0,1,1,1,0,0,0,1}, {1,1,0,0,1,1,1,0,1,1}, {1,1,1,0,0,0,0,0,1,1}, {1,1,1,1,0,0,1,0,1,1}, {1,0,0,0,0,1,1,0,0,1}, {1,0,1,1,1,0,1,1,0,1}, {1,1,1,1,1,1,1,1,1,1} }; }
接下来是A*算法的使用代码:
using UnityEngine; using System.Collections; using System; using System.Collections.Generic; public enum Grids3DType { Normal, Obstacle, Start, End } public class Grids_3D : IComparable { public int x; public int y; public int G; public int F; public int H; public Grids_3D fatherMode; public Grids3DType gridsType; public int CompareTo(object obj) { Grids_3D grid = (Grids_3D)obj; if (this.F < grid.F) return -1; else if (this.F > grid.F) return 1; return 0; } } public class AStart_3D : MonoBehaviour { private int[,] MazeItem; // 迷宫数组 private GameObject npc; private const int xStart = 1; private const int yStart = 1; private const int xEnd = 8; private const int yEnd = 8; private bool noroad = false; // 没有路 private Grids_3D[,] map; // private Vector3 target = Vector3.zero; // 当前要前往的目标点 private float speed = 4; // 小球移动速度 ArrayList openList; // 开放列表 ArrayList closeList; // 关闭列表 private List<Vector3> path; // 存储要移动的路径 private int n = 0; // 当前已经移动的路点 // Use this for initialization void Start () { MazeItem = MapsArray.MazeItem; // 初始化迷宫数组 openList = new ArrayList(); closeList = new ArrayList(); path = new List<Vector3>(); StartCoroutine(CreateMap()); } void Update() { if (target != Vector3.zero) { if (path.Count > 0) { npc.transform.position = Vector3.MoveTowards(npc.transform.position, target, Time.deltaTime * speed); if (npc.transform.position == target) { target = GetTarget(); } } } } // 创建地图 IEnumerator CreateMap() { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); yield return cube; for (int i = 0; i < MazeItem.GetLength(0); i++) { for (int j = 0; j < MazeItem.GetLength(1); j++) { if (MazeItem[i, j] == 1) { Instantiate(cube, new Vector3(i, j, 0), Quaternion.identity); } } } // 起始点标记 GameObject start = Instantiate(cube, new Vector3(xStart, yStart, 0), Quaternion.identity) as GameObject; start.transform.localScale = Vector3.one * 0.3f; start.renderer.material.color = Color.grey; GameObject end = Instantiate(cube, new Vector3(xEnd, yEnd, 0), Quaternion.identity) as GameObject; end.transform.localScale = Vector3.one * 0.3f; end.renderer.material.color = Color.blue; yield return new WaitForEndOfFrame(); StartCoroutine(CreateNPC()); } // 创建NPC IEnumerator CreateNPC() { GameObject npc_Prefab = GameObject.CreatePrimitive(PrimitiveType.Sphere); yield return npc_Prefab; if (MazeItem[1, 1] == 0) { npc = Instantiate(npc_Prefab, new Vector3(1, 1, 0), Quaternion.identity) as GameObject; npc.renderer.material.color = Color.red; target = npc.transform.position; // 设置初始点 } yield return new WaitForEndOfFrame(); StartCoroutine(Pathing()); } // 开始寻路 IEnumerator Pathing() { InitMap(); // 初始化地图, 标记地图起点、终点、障碍物 yield return new WaitForEndOfFrame(); while (!noroad) // 如果不是没有路,就继续寻路 { Pathing_OneStep(); } } // 初始化地图, 标记地图起点、终点、障碍物 void InitMap() { map = new Grids_3D[MazeItem.GetLength(0), MazeItem.GetLength(1)]; for (int i = 0; i < MazeItem.GetLength(0); i++) { for (int j = 0; j < MazeItem.GetLength(1); j++) { map[i, j] = new Grids_3D(); map[i, j].x = i; map[i, j].y = j; if (MazeItem[i, j] == 0) { map[i, j].gridsType = Grids3DType.Normal; } else { map[i, j].gridsType = Grids3DType.Obstacle; } } } map[xStart, yStart].gridsType = Grids3DType.Start; map[xStart, yStart].H = ManHattan(xEnd, yEnd); map[xEnd, yEnd].gridsType = Grids3DType.End; openList.Add(map[xStart, yStart]); } //曼哈顿算法,求H的值 int ManHattan(int x, int y) { return (int)(Mathf.Abs(x - xEnd) + Mathf.Abs(y - yEnd)) * 10; } // 进行一步寻路计算获取最短路径 void Pathing_OneStep() { // 如果开放列表为0,则返回,并标记为没有路 if (openList.Count == 0) { noroad = true; return; } Grids_3D grid = (Grids_3D)openList[0]; // 如果到达终点,则回溯获取路径,并返回没有路 if (grid.gridsType == Grids3DType.End) { ShowFatherNode(grid); // 通过父节点回溯 noroad = true; return; } for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (!(i == 0 && j == 0) && ((i == 0 && j != 0) || (j == 0 && i != 0))) { int x = grid.x + i; int y = grid.y + j; if (x >= 0 && x < MazeItem.GetLength(0) && y >= 0 && y < MazeItem.GetLength(1) && !closeList.Contains(map[x, y]) && map[x, y].gridsType != Grids3DType.Obstacle) { int g = grid.G + (int)(Mathf.Sqrt(Mathf.Abs(i) + Mathf.Abs(j)) * 10); if (map[x, y].G == 0 || g < map[x, y].G) { map[x, y].G = g; } map[x, y].H = ManHattan(x, y); map[x, y].F = map[x, y].G + map[x, y].H; map[x, y].fatherMode = grid; if (!openList.Contains(map[x, y])) { openList.Add(map[x, y]); } openList.Sort(); } } } } closeList.Add(grid); openList.Remove(grid); } // 通过回溯找到最短路径 void ShowFatherNode(Grids_3D grid) { if (grid.fatherMode != null) { Vector3 point = new Vector3(grid.x, grid.y, 0); path.Add(point); ShowFatherNode(grid.fatherMode); } } // 获取路径 Vector3 GetTarget() { Vector3 point = npc.transform.position; if (path.Count > 0 && n < path.Count) { point = path[path.Count - n - 1]; n++; } return point; } }
时间: 2024-11-06 07:32:29