02.A*

链接:https://pan.baidu.com/s/15j770Uf5IVp3lDskSI-0TA 密码:xq10
在这里插入图片描述
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 格子的类型
/// </summary>
public enum NodeType
{
    Walk,
    Stop,
}

/// <summary>
/// 格子类
/// </summary>
public class AStarNode
{
    //格子的坐标
    public int x;
    public int y;

    //寻路消耗
    public float f;
    //距离起点的距离
    public float g;
    //距离终点的距离(曼哈顿距离)
    public float h;

    //格子的父物体
    public AStarNode Father;

    //格子的类型
    public NodeType Type;

    public AStarNode(int x,int y,NodeType nodeType)
    {
        this.x = x;
        this.y = y;
        this.Type = nodeType;
    }
    
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 格子管理器
/// </summary>
public class AStarMgr 
{
   private AStarMgr() { }
   private static AStarMgr _instance;
   public static AStarMgr Instance
   {
       get
       {
           if (_instance==null)
           {
               _instance=new AStarMgr();
           }
           return _instance;
       }
   }

   //地图的宽高
   private int mapW;
   private int mapH;

   //地图相关所有的格子对象容器
   public AStarNode[,] nodes;
   //开启列表
   private List<AStarNode> openList=new List<AStarNode>();
   //关闭列表
   private List<AStarNode> closeList=new List<AStarNode>();

   public void InitMapInfo(int w,int h)
   {
       this.mapW = w;
       this.mapH = h;
       nodes=new AStarNode[w,h];
       for (int i = 0; i < w; i++)
       {
           for (int j = 0; j < h; j++)
           {
               AStarNode node=new AStarNode(i,j,UnityEngine.Random.Range(0,100)<20?NodeType.Stop:NodeType.Walk);
               nodes[i, j] = node;
           }
       }
   }

    //寻路方法
    public List<AStarNode> FindPath(Vector2 startPos, Vector2 endPos)
    {
        //首先判断传入的点上方合法
        //01. 在地图的范围内
        if (startPos.x < 0 || startPos.x >= mapW || startPos.y < 0 || startPos.y >= mapH)
        {
            return null;
        }
        if (endPos.x<0||endPos.x>=mapW||endPos.y<0||endPos.y>=mapH)
        {
            return null;
        }

        //02.不是阻挡
        //得到起点和终点对应的格子
        AStarNode start = nodes[(int)startPos.x, (int)startPos.y];
        AStarNode end = nodes[(int)endPos.x, (int)endPos.y];
        //如果不合法,自己返回为空不能寻路
        if (start.Type==NodeType.Stop||end.Type== NodeType.Stop)
        {
            return null;
        }
       
        //清空开启和关闭列表 上一次寻路的数据给清除掉
        openList.Clear();
        closeList.Clear();
        //将开始点放入关闭列表
        start.Father = null;
        start.f = 0;
        start.g = 0;
        start.h = 0;
        closeList.Add(start);
        while (true)
        {
            //从起点开始 找周围的点 并放入开启列表中
            //左上  x-1  y-1
            FinNearlyNodeToOpenList(start.x - 1, start.y - 1, 1.4f, start, end);
            //上    x y-1
            FinNearlyNodeToOpenList(start.x, start.y - 1, 1f, start, end);
            //右上  x+1 y-1
            FinNearlyNodeToOpenList(start.x + 1, start.y - 1, 1.4f, start, end);
            //左    x-1 y 
            FinNearlyNodeToOpenList(start.x - 1, start.y, 1f, start, end);
            //右    x+1 y
            FinNearlyNodeToOpenList(start.x + 1, start.y, 1f, start, end);
            //左下  x-1 y+1
            FinNearlyNodeToOpenList(start.x - 1, start.y + 1, 1.4f, start, end);
            //下    x y+1
            FinNearlyNodeToOpenList(start.x, start.y + 1, 1f, start, end);
            //右下  x+1 y+1
            FinNearlyNodeToOpenList(start.x + 1, start.y + 1, 1.4f, start, end);

            //死路判断 开启列表为空
            if (openList.Count==0)
            {
                return null;
            }
            //选出开启列表中寻路消耗最小的点
            openList.Sort(SortOpenList);
            //放入关闭列表中 然后再从开启列表中移除
            closeList.Add(openList[0]);
            //找到这个最近的点openList[0],进行下一次的寻路计算
            start = openList[0];
            openList.RemoveAt(0);

            //如果这个点已经是终点了 那么得到最终结果返回出去
            if (start == end)
            {
                //找到了
                List<AStarNode> path=new List<AStarNode>();
                path.Add(end);
                while (end.Father!=null)
                {
                    path.Add(end.Father);
                    end = end.Father;
                }
                path.Reverse();
                return path;
            }
            //如果这个点 不是终点 那么继续寻路
        }

    }

    //找到一个相邻的点放入OpenList中
    //判断这些点 是否是边界 是否是阻挡 是否在开启和关闭列表中如果不是 才计算
    private void FinNearlyNodeToOpenList(int x,int y,float g,AStarNode father, AStarNode end)
    {
        if (x<0||x>=mapW||y<0||y>=mapH)
        {
            return;
        }
        AStarNode node = nodes[x, y];
        //OpenList和CloseList中是否包含这个点
        if (node==null||node.Type==NodeType.Stop||openList.Contains(node)||closeList.Contains(node))
        {
           return;    
        }

        node.Father = father;
        //计算f值
        node.g = father.g + g;
        node.h = Mathf.Abs(end.x - node.x) + Mathf.Abs(end.y - node.y);
        node.f = node.g + node.f;
        openList.Add(node);
    }


    private int SortOpenList(AStarNode a,AStarNode b) 
    {
        if (a.f>b.f)
        {
            return 1;
        }
        else if (a.f==b.f)
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;


public enum ColorType
{
    Normal,
    Yellow,
    Red,
    Green,
}
public class GameManager : MonoBehaviour
{
    private GameManager(){}
    private static GameManager _instance;
    public static GameManager Instance
    {
        get {
            if (_instance==null)
            {
                _instance = GameObject.FindObjectOfType<GameManager>();
            }
            return _instance;
        }
    }

    public int beginX=3;
    public int beginY=5;
    public int offsetX=2;
    public int offsetY=-2;
    public int mapW=5;
    public int mapH=8;
    public Dictionary<ColorType, Material> materialDic;
    
    private Dictionary<GameObject, AStarNode> starNodeDic;

    List<AStarNode> nodes=new List<AStarNode>();
    void Awake()
    {
        materialDic =new Dictionary<ColorType, Material>();
        starNodeDic=new Dictionary<GameObject, AStarNode>();
        materialDic.Add(ColorType.Normal, Resources.Load<Material>("Normal"));
        materialDic.Add(ColorType.Red,Resources.Load<Material>("Red"));
        materialDic.Add(ColorType.Yellow, Resources.Load<Material>("Yellow"));
        materialDic.Add(ColorType.Green, Resources.Load<Material>("Green"));
        AStarMgr.Instance.InitMapInfo(mapW,mapH);
        for (int i = 0; i < mapW; i++)
        {
            for (int j = 0; j < mapH; j++)
            {
                GameObject item = GameObject.CreatePrimitive(PrimitiveType.Cube);
                item.transform.SetParent(this.transform);
                item.transform.position=new Vector3(beginX+i*offsetX,beginY+j* offsetY);
                item.name = i + "_" + j;
                AStarNode node = AStarMgr.Instance.nodes[i, j];
                switch (node.Type)
                {
                    case NodeType.Stop:
                        item.transform.GetComponent<MeshRenderer>().material = materialDic[ColorType.Red];
                        break;
                }
                starNodeDic.Add(item,node);
            }
        }

    }


    private int pos = 1;
    private Vector2 begin;
    private GameObject beginObj;
    private List<AStarNode> list;
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit info;
            Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray,out info,1000))
            {
                pos += 1;
                if (pos%2==0)
                {
                    //清空之前的颜色
                    if (list!=null)
                    {
                        for (int i = 0; i < list.Count; i++)
                        {
                            foreach (var nodes in starNodeDic)
                            {
                                if (nodes.Value == list[i])
                                {
                                    nodes.Key.gameObject.transform.GetComponent<MeshRenderer>().material = materialDic[ColorType.Normal];
                                }
                            }
                        }
                    }

                    beginObj = info.collider.gameObject;
                    begin = new Vector2(starNodeDic[info.collider.gameObject].x, starNodeDic[info.collider.gameObject].y);
                    info.collider.gameObject.transform.GetComponent<MeshRenderer>().material = materialDic[ColorType.Yellow];
                }
                else
                {
                    Vector2  end = new Vector2(starNodeDic[info.collider.gameObject].x, starNodeDic[info.collider.gameObject].y);
                     list =AStarMgr.Instance.FindPath(begin, end);
                    if (list!=null)
                    {
                        for (int i = 0; i < list.Count; i++)
                        {
                            foreach (var nodes in starNodeDic)
                            {
                                if (nodes.Value==list[i])
                                {
                                    nodes.Key.gameObject.transform.GetComponent<MeshRenderer>().material = materialDic[ColorType.Green];
                                }
                            }
                        }
                    }
                    else
                    {
                        //是死路的时候 清空开始点的颜色
                        beginObj.gameObject.transform.GetComponent<MeshRenderer>().material = materialDic[ColorType.Normal];
                    }
                    
                }
              
            }
        }
    }

}


版权声明:本文为weixin_33950757原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。