Unity3D之迷宫寻路_A*最短路径寻路

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;
    }
}



猜你喜欢

转载自blog.csdn.net/a3636987/article/details/45564219