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;
    }
}
时间: 2024-08-28 21:09:00

Unity3D之迷宫寻路_A*最短路径寻路的相关文章

Unity3D之迷宫寻路使用_直接寻路

学了一段时间的寻路,在网上也学了挺多算法,今天整理了一下,使用到Unity的3D界面中用于寻路,首先是简单的寻路算法,以下是地图: 地图数组: 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

[Unity3D]Unity3D游戏开发之自己主动寻路与Mecanim动画系统的结合

大家好,欢迎大家关注我的博客,我是秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 这段时间博主将大部分的精力都放在了研究官方演示样例项目上,主要是希望能够从中挖掘出有价值的东西分享给大家.这样博主和大家能够共同学习.好了,那么今天博主想和大家分享的是自己主动寻路与Mecanim动画系统结合起来实现的一个小案例,希望对大家学习Unity3D能够有所帮助. 博主以前告诉大家.博主是一个仙剑迷,平时学习编程累了的时候,博主就会玩玩仙剑.如图是博主偶尔回去玩玩的<新仙剑OL>

寻路搜索 最短路径等问题

1:游戏中的A*算法: http://gad.qq.com/article/detail/31753 2:算法比较 http://blog.csdn.net/hopeping128/article/details/78960326 https://www.cnblogs.com/v-July-v/archive/2011/03/10/2009186.html  作者:July https://www.zhihu.com/question/264734535 一并附上Dijkstar介绍:http

Unity3D游戏开发之 (Navmesh) 和寻路 (Pathfinding)烘焙

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,我们致力于打造业内unity3d培训.学习第一品牌. 导航网格烘焙 一旦标记完导航网格 (Navmesh) 几何体和层之后,就可以烘焙导航网格几何体了. 在导航 (Navigation) 窗口中(窗口 (Window)->导航 (Navigation)),转到烘焙 (Bake) 选项卡(右上角),然后点击"烘焙"按钮(右下角). 导

求迷宫多条最短路径

#include <iostream> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <stack> using namespace std; const int SIZE = 102; //边界数组,四个方向,按照下.右.上.左的顺序 int coordinate[4]

一种高效的寻路算法 - B*寻路算法

在此把这个算法称作B* 寻路算法(Branch Star 分支寻路算法,且与A*对应),本算法适用于游戏中怪物的自动寻路,其效率远远超过A*算法,经过测试,效率是普通A*算法的几十上百倍. 通过引入该算法,一定程度上解决了游戏服务器端无法进行常规寻路的效率问题,除非服务器端有独立的AI处理线程,否则在服务器端无法允许可能消耗大量时间的寻路搜索,即使是业界普遍公认的最佳的A*,所以普遍的折中做法是服务器端只做近距离的寻路,或通过导航站点缩短A*的范围. 算法原理  本算法启发于自然界中真实动物的寻

关于A*寻路算法的认识

最近要参加学校的APP比赛,我们组做的是一个3D迷宫的小APP,我负责的是迷宫的生成与寻路. 寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客. 本文主要是谈谈自己对A*算法的理解,具体细节,上文链接以及讲的很详细了. http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html 关于A*算法的实现我是用的广度优先搜索这种比较常见的实现模式. 那么关于这两者之间的关系是怎么样呢? 个人理解的是A*算法其实是一种带有路径

一道广搜寻路题

同样是在qq群里看到的题目,想了好久算法,实现也用了很久. 关于题目首先看图: 总的来说,就是一个二维迷宫的寻路,迷宫中有对应的钥匙和刺,每走一步会消耗1点Hp,当走到刺上时会额外消耗100点hp,持有对应颜色的钥匙通过刺时不用额外消耗Hp. 给予起点和终点的坐标,,输出移动方式,让人物抵达终点所消耗的Hp尽可能的小. 例子: 3 3 1..a##A...1 13 3这个是输入数据 第一个代表高 第二个宽 第三个是钥匙和陷阱的对数 .代表平地 #代表墙 小写字母是钥匙 大写字母是对应的陷阱输出为

从 NavMesh 网格寻路回归到 Grid 网格寻路。

上一个项目的寻路方案是客户端和服务器都采用了 NavMesh 作为解决方案,当时的那几篇文章(一,二,三)是很多网友留言和后台发消息询问最多的,看来这个方案有着广泛的需求.但因为是商业项目,我无法贴出代码,只能说明下我的大致思路,况且也有些悬而未决的不完美的地方,比如客户端和服务器数据准确度和精度的问题,但是考虑到项目类型和性价比,我们忽略了这个点. 从今年5月份开始为期一个月,我的主要工作是为新项目寻找一个新的寻路方案.新项目是一个 RTS 实时竞技游戏,寻路要求是:每个寻路单位之间的碰撞精确