链接: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版权协议,转载请附上原文出处链接和本声明。