您的位置:首页 > 移动开发 > Unity3D

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息