Unity3D之迷宫寻路_A*最短路径寻路
2015-05-07 17:44
225 查看
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;
}
}
接下来是地图数组:
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;
}
}
相关文章推荐
- 挑战程序设计竞赛 2.1迷宫的最短路径
- 迷宫求解最短路径问题java版
- 迷宫的最短路径之BFS算法
- 宽度优先搜索——迷宫的最短路径
- 也谈迷宫算法(最短路径 队列)+源程序
- 迷宫的最短路径
- 迷宫问题之最短路径bfs
- 《挑战程序设计比赛》 P35 题目:迷宫的最短路径 广度搜索
- 51nod1459 迷宫游戏(相当于最短路径,含2个权值)
- 5X5迷宫,求起点和终点的最短路径以及最短路径个数(百分数)
- [Unity3D]A*算法、导航网格、路径点寻路对比(A-Star VS NavMesh VS WayPoint)
- 迷宫最短路径
- 【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)
- 自动寻找走出迷宫的最短路径
- 模拟最短路径寻路(JAVA界面)
- 使用栈求解迷宫最短路径
- POJ 3322 Bloxorz I(BFS:求迷宫最短路径)
- DFS走迷宫问题(非最短路径)
- 递归和栈求解迷宫的最短路径
- 迷宫最短路径长度bfs