版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18192161/article/details/79262081
OK,A*的算法在网上有很多,当初我书写A*的时候参考的就是网络文章,下面附上链接
http://www.360doc.com/content/16/1201/12/99071_610999046.shtml
根据A*的算法来看,我们需要将地图划分为一个一个格子,然后标记处可行走的区域和不可行走的区域,然后经过计算得到一条两点之间的路径。
首先我们先实现将地图划分为N个格子。
实现方法:
1.在高度100(可设置)的地方超地面投射50*50(可设置),间距为(0.5*0.5)(可设置)的矩阵射线
2.检测射线碰撞体为Ground(10)(可设置),存储改点状态为可行走区域
脚本MapPath:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class MapPath : MonoBehaviour {
public static MapPath Instance;
/// <summary>
/// 是否绘制Gizmos
/// </summary>
public bool IsGizmos = false;
/// <summary>
/// 可行走节点
/// </summary>
[HideInInspector]
public List< MapGridInfo> gridItem = new List<MapGridInfo>();
/// <summary>
/// 可行走节点名称
/// </summary>
[HideInInspector]
public List<string> gridItemName = new List<string>();
/// <summary>
/// 寻找的路径
/// </summary>
private List<PathFinding> pathFindnig = new List<PathFinding>();
/// <summary>
/// 检测层
/// </summary>
public int DetLayer = 0;
/// <summary>
/// 格子尺寸
/// </summary>
public Vector2 MapGridSize = new Vector2(1, 1);
/// <summary>
/// 格子数量
/// </summary>
public Vector2 MapGridNum = new Vector2(100, 100);
/// <summary>
/// 射线投放高度
/// </summary>
public float DetHeight = 100;
//private APath Apath;
private List<MapGridInfo> pathStr = new List<MapGridInfo>();
/// <summary>
/// 主线程事件
/// </summary>
public static Stack<Action> MainThreadAction = new Stack<Action>();
void Awake()
{
Instance = this;
GUITools.ResterWindowAction(new Rect(0,150,200,160),delegate(GUIAction action) {
action.Rect= GUI.Window(action.Id,action.Rect,delegate {
GUI.Label(new Rect(5,20,80,20),"Start Point:");
action.Param[0] = GUI.TextField(new Rect(75,20,40,20) ,action.Param[0]);
action.Param[1] = GUI.TextField(new Rect(125,20,40, 20), action.Param[1]);
GUI.Label(new Rect(5, 45, 80, 20), "End Point:");
action.Param[2] = GUI.TextField(new Rect(75, 45, 40, 20), action.Param[2]);
action.Param[3] = GUI.TextField(new Rect(125, 45, 40, 20), action.Param[3]);
action.Param[4] = GUI.Toggle(new Rect(5, 70, 50, 20), bool.Parse(action.Param[4]),"IsPathMove").ToString();
if(bool.Parse(action.Param[4]))
action.Param[5] = GUI.TextField(new Rect(5, 95, 190, 20), action.Param[5]);
if (GUI.Button(new Rect(5, 120, 190, 30), "Find Path"))
{
pathStr.Clear();
if (bool.Parse(action.Param[4]))
{
Actor TestActor = null;
GameObject obj = GameObject.Find(action.Param[5]);
if (obj != null)
TestActor = obj.GetComponent<Actor>();
if (TestActor != null)
FindPaht(TestActor, new Vector3(float.Parse(action.Param[2]),0, float.Parse(action.Param[3])), null);
}
else
{
//List<Vector2> pathPoint = GetPath(GetPos(new Vector2(float.Parse(action.Param[0]), float.Parse(action.Param[1]))), GetPos(new Vector2(float.Parse(action.Param[2]), float.Parse(action.Param[3]))));
//for (int i = 0; i < pathPoint.Count; i++)
//pathStr.Add(GetGridInfo(GetGridName(pathPoint[i])));
}
}
GUI.DragWindow();
},action.Id+ "- A* Path|MapPath");
},"0","0","0","0","false","Player");
APath.IsWalk = delegate (Vector2 pos) {
return IsWalk(pos);
/*
MapGridInfo info = GetGridInfo(name);
if (info != null)
return info.IsWalk;
return false;
*/
};
APath.IsObstacles = delegate (Vector2 pos1, Vector2 pos2)
{
Vector3 newPos1 = new Vector3(pos1.x * MapGridSize.x, 0, pos1.y * MapGridSize.y);
Vector3 newPos2 = new Vector3(pos2.x * MapGridSize.x, 0, pos2.y * MapGridSize.y);
return IsObstaclesTwoPoint(newPos1, newPos2);
};
}
void Update()
{
while (MainThreadAction.Count > 0) MainThreadAction.Pop()();
for (int i = 0; i < pathFindnig.Count; i++)
pathFindnig[i].OnTick();
}
void OnDrawGizmos()
{
if (Instance == null)
Instance = this;
if (IsGizmos)
{
OnDrawPoint();
}
}
/// <summary>
/// 绘制给子
/// </summary>
void OnDrawPoint()
{
foreach (var data in gridItem)
{
if (!data.IsWalk) return;
if (pathStr.Contains(data))
{
data.DrawGizmos(delegate { Gizmos.color = Color.yellow; });
}
else
data.DrawGizmos();
}
}
/// <summary>
/// 是否可以行走
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
public bool IsWalk(Vector3 pos)
{
string name = GetGridName(GetPos(pos));
if (gridItemName.Contains(name))
return true;
return false;
}
/// <summary>
/// 是否可以行走
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
public bool IsWalk(Vector2 pos)
{
string name = GetGridName(pos.x, pos.y);
if (gridItemName.Contains(name))
return true;
return false;
}
/// <summary>
/// 生成地图给子
/// </summary>
public void DetMapGrid()
{
gridItem.Clear();
gridItemName.Clear();
for (int i = 0; i < MapGridNum.x; i++)
{
//yield return new WaitForSeconds(0.02f);
for (int j = 0; j < MapGridNum.y; j++)
{
//yield return new WaitForSeconds(0.02f);
Vector3 pos = new Vector3(MapGridSize.x * i + MapGridSize.x / 2f, DetHeight, MapGridSize.y * j + MapGridSize.y / 2f);
MapGridInfo info = new MapGridInfo(pos, i + "-" + j);
if (info.IsWalk)
{
gridItemName.Add(info.GridName);
gridItem.Add(info);
}
}
}
Debug.Log("地图配置完毕....");
}
/// <summary>
/// 查找路径
/// </summary>
/// <param name="actor"></param>
/// <param name="end"></param>
/// <param name="OnFinsh"></param>
public void FindPaht(Actor actor,Vector3 end,Action<float> OnFinsh)
{
if (actor != null)
{
pathStr.Clear();
Vector2 actorPos = GetPos(actor.position);
Vector2 endPos = GetPos(end);
if (actorPos == endPos) return;
if (!gridItemName.Contains(GetGridName(endPos))) return;
actor.OnPathFinshEvent = OnFinsh;
actor.OnFindPathFinshEvent = delegate(Actor actor1,List<Vector2> path){
OnFindPathFinsh(actor1, path, actor1.OnPathFinshEvent);
};
if (!IsObstaclesTwoPoint(actor.position, end))
{
OnFindPathFinsh(actor, new List<Vector2>() { GetPos(end) },OnFinsh);
//info.Add(GetGridInfo(GetGridName(endPos)));
}
else
{
ProfilerTools.BeginSample("A* Path", delegate
{
APath.FindPath(actor, actorPos, endPos);
//GetPath(actor, actorPos, endPos); ;
});
}
}
}
/// <summary>
/// 路径查找结束
/// </summary>
/// <param name="actor"></param>
/// <param name="path"></param>
/// <param name="OnFinsh"></param>
public void OnFindPathFinsh(Actor actor, List<Vector2> path, Action<float> OnFinsh)
{
List<MapGridInfo> info = new List<MapGridInfo>();
for (int i = 0; i < path.Count; i++)
pathStr.Add(GetGridInfo(GetGridName(path[i])));
info.AddRange(pathStr);
PathFinding pathF = GetPathFinding(actor);
if (pathF != null)
{
pathF.ChangePath(info);
return;
}
PathFinding pf = new PathFinding(actor, info);
pf.OnFinsh = delegate (float time)
{
pathFindnig.Remove(pf);
if (OnFinsh != null)
OnFinsh(time);
};
pathFindnig.Add(pf);
}
/// <summary>
/// 两点之间是否可直接通行
/// </summary>
/// <param name="pos1"></param>
/// <param name="pos2"></param>
/// <returns></returns>
public bool IsObstaclesTwoPoint(Vector3 pos1,Vector3 pos2)
{
Vector3 dir = pos1 - pos2;
float dis = Vector3.Distance(pos1,pos2);
float num = dis / MapGridSize.x;
bool isObstacle = false;
for (int i = 1; i < num; i++)
{
Vector3 detPos = pos2 + dir.normalized * (MapGridSize.x*i);
if (!IsWalk(detPos))
isObstacle = true;
}
return isObstacle;
}
/// <summary>
/// 获取路径
/// </summary>
/// <param name="actor"></param>
/// <returns></returns>
public PathFinding GetPathFinding(Actor actor)
{
for (int i = 0; i < pathFindnig.Count; i++)
{
if (pathFindnig[i].Actor == actor)
return pathFindnig[i];
}
return null;
}
/// <summary>
/// 获取格子信息
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public MapGridInfo GetGridInfo(string name)
{
for (int i = 0; i < gridItem.Count; i++)
{
if (gridItem[i].GridName.Equals(name))
return gridItem[i];
}
return null;
}
/// <summary>
/// 坐标转换
/// </summary>
/// <param name="gridPos"></param>
/// <returns></returns>
public Vector2 GetPos(Vector2 gridPos)
{
return new Vector2(((int)(gridPos.x / MapGridSize.x)), ((int)(gridPos.y / MapGridSize.y)));
}
/// <summary>
/// 坐标转换
/// </summary>
/// <param name="gridPos"></param>
/// <returns></returns>
public Vector2 GetPos(Vector3 gridPos)
{
return new Vector2(((int)(gridPos.x / MapGridSize.x)), ((int)(gridPos.z / MapGridSize.y)));
}
/// <summary>
/// 获取名称
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public string GetGridName(float x,float y)
{
return x+ "-" + y;
}
/// <summary>
/// 获取名称
/// </summary>
/// <param name="gridPos"></param>
/// <returns></returns>
public string GetGridName(Vector3 gridPos)
{
return gridPos.x + "-" + gridPos.z;
}
/// <summary>
/// 获取名称
/// </summary>
/// <param name="gridPos"></param>
/// <returns></returns>
public string GetGridName(Vector2 gridPos)
{
return gridPos.x + "-" + gridPos.y;
}
}
这个类的主要功能:
1.在编辑器中绘制并显示mesh
/// <summary>
/// 生成地图给子
/// </summary>
public void DetMapGrid()
{
gridItem.Clear();
gridItemName.Clear();
for (int i = 0; i < MapGridNum.x; i++)
{
//yield return new WaitForSeconds(0.02f);
for (int j = 0; j < MapGridNum.y; j++)
{
//yield return new WaitForSeconds(0.02f);
Vector3 pos = new Vector3(MapGridSize.x * i + MapGridSize.x / 2f, DetHeight, MapGridSize.y * j + MapGridSize.y / 2f);
MapGridInfo info = new MapGridInfo(pos, i + "-" + j);
if (info.IsWalk)
{
gridItemName.Add(info.GridName);
gridItem.Add(info);
}
}
}
Debug.Log("地图配置完毕....");
}
2.查找路径
/// <summary>
/// 查找路径
/// </summary>
/// <param name="actor"></param>
/// <param name="end"></param>
/// <param name="OnFinsh"></param>
public void FindPaht(Actor actor,Vector3 end,Action<float> OnFinsh)
{
if (actor != null)
{
pathStr.Clear();
Vector2 actorPos = GetPos(actor.position);
Vector2 endPos = GetPos(end);
if (actorPos == endPos) return;
if (!gridItemName.Contains(GetGridName(endPos))) return;
actor.OnPathFinshEvent = OnFinsh;
actor.OnFindPathFinshEvent = delegate(Actor actor1,List<Vector2> path){
OnFindPathFinsh(actor1, path, actor1.OnPathFinshEvent);
};
if (!IsObstaclesTwoPoint(actor.position, end))
{
OnFindPathFinsh(actor, new List<Vector2>() { GetPos(end) },OnFinsh);
//info.Add(GetGridInfo(GetGridName(endPos)));
}
else
{
ProfilerTools.BeginSample("A* Path", delegate
{
APath.FindPath(actor, actorPos, endPos);
//GetPath(actor, actorPos, endPos); ;
});
}
}
}
类:MapGridInfo 格子的详细信息
[SerializeField]
[System.Serializable]
public class MapGridInfo
{
/// <summary>
/// 格子名称
/// </summary>
public string GridName;
/// <summary>
/// 格子坐标
/// </summary>
public Vector3 GridPos;
/// <summary>
/// 是否可以行走
/// </summary>
public bool IsWalk;
/// <summary>
/// 网格信息
/// </summary>
private Mesh _meshInfo;
public Mesh MeshInfo {
get {
if (_meshInfo == null)
{
IsWalk = Ray();
SetMesh();
}
return _meshInfo;
}
}
/// <summary>
/// 绘制高度
/// </summary>
public float Height;
/// <summary>
/// 颜色
/// </summary>
public Color GizmosColor;
public MapGridInfo(Vector3 gridPos,string gridName)
{
GridName = gridName;
GridPos = gridPos;
IsWalk = Ray();
SetMesh();
}
/// <summary>
/// 设置网格
/// </summary>
void SetMesh()
{
Mesh mesh = new Mesh();
List<Vector3> vertices = new List<Vector3>();
vertices.Add(new Vector3(GridPos.x + GetSize.x / 2, Height, GridPos.z + GetSize.y / 2));
vertices.Add(new Vector3(GridPos.x + GetSize.x / 2, Height, GridPos.z - GetSize.y / 2));
vertices.Add(new Vector3(GridPos.x - GetSize.x / 2, Height, GridPos.z - GetSize.y / 2));
vertices.Add(new Vector3(GridPos.x - GetSize.x / 2, Height, GridPos.z + GetSize.y / 2));
mesh.vertices = vertices.ToArray();
List<int> tri = new List<int>();
tri.Add(0);
tri.Add(1);
tri.Add(2);
tri.Add(0);
tri.Add(2);
tri.Add(3);
mesh.triangles = tri.ToArray();
mesh.RecalculateBounds();
mesh.RecalculateNormals();
_meshInfo = mesh;
}
/// <summary>
/// 获取尺寸
/// </summary>
Vector2 GetSize
{
get{ return new Vector2(MapPath.Instance.MapGridSize.x - MapPath.Instance.MapGridSize.x*0.1f, MapPath.Instance.MapGridSize.y - MapPath.Instance.MapGridSize.y*0.1f); }
}
/// <summary>
/// 绘制格子
/// </summary>
/// <param name="OnChangeColor"></param>
public void DrawGizmos(System.Action OnChangeColor = null)
{
Gizmos.color = GizmosColor;
if (OnChangeColor != null)
OnChangeColor();
Gizmos.DrawMesh(MeshInfo);
}
/// <summary>
/// 投送射线
/// </summary>
/// <returns></returns>
private bool Ray()
{
RaycastHit hitInfo;
if (Physics.Raycast(GridPos, Vector3.down, out hitInfo, MapPath.Instance.DetHeight + 50))
{
if (hitInfo.collider.gameObject.layer == MapPath.Instance.DetLayer)
{
GizmosColor = Color.green;
Height = hitInfo.point.y + 0.1f;
return true;
}
}
GizmosColor = Color.red;
return false;
}
}
主要实现功能:
1.存储格子的相关信息,比如坐标,名称,是否可行走,mesh信息等
2.投放射线检测目标是否可以行走
3.绘制mesh在编辑器进行显示
类:PathFinding
/// <summary>
/// 路径移动
/// </summary>
public class PathFinding
{
/// <summary>
/// 角色
/// </summary>
public Actor Actor { get; private set; }
/// <summary>
/// 查找的路径
/// </summary>
public List<MapGridInfo> PathPoint { get; private set; }
/// <summary>
/// 当前点
/// </summary>
public MapGridInfo CurPoint { get; private set; }
/// <summary>
/// 时间
/// </summary>
private float RunTime = 0;
/// <summary>
/// 结束事件
/// </summary>
public Action<float> OnFinsh { get; set; }
public PathFinding(Actor actor,List<MapGridInfo> pathPoint) {
Actor = actor;
PathPoint = pathPoint;
CurPoint = GetNetPoint;
}
public void ChangePath(List<MapGridInfo> pathPoint)
{
PathPoint = pathPoint;
CurPoint = GetNetPoint;
}
/// <summary>
/// 获取下一个点
/// </summary>
MapGridInfo GetNetPoint {
get {
if (PathPoint.Count > 0)
{
MapGridInfo mi = PathPoint[0];
PathPoint.RemoveAt(0);
return mi;
}
if (OnFinsh != null)
OnFinsh(RunTime);
return null;
}
}
/// <summary>
/// 循环事件
/// </summary>
public void OnTick()
{
if (CurPoint != null)
{
RunTime += Time.deltaTime;
Actor.SetPathMove(CurPoint.GridPos,0.1f,delegate {
CurPoint = GetNetPoint;
if (CurPoint == null)
Actor.SetIdleState();
},delegate {
if (OnFinsh != null)
OnFinsh(RunTime);
} );
}
}
}
此类的功能:
1.主要实现控制角色跟随路径进行移动
A* 的主要算法类:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEditor.VersionControl;
using UnityEngine;
/// <summary>
/// A*寻路
/// </summary>
public class APath
{
public static Stack<APath> Pool = new Stack<APath>();
public static APath Create()
{
if (Pool.Count < 1)
return new APath();
return Pool.Pop();
}
public static void FindPath(Actor actor,Vector2 start, Vector2 end)
{
APath aPath = APath.Create();
aPath.SetStartPoint(start);
aPath.SetEndPoint(end);
ThreadPool.QueueUserWorkItem(new WaitCallback(aPath.GetPath),actor);
}
private List<APoint> Close = new List<APoint>();
private List<APoint> Open = new List<APoint>();
//private MapGridData gridData;
/*
public APath(MapGridData _gridData)
{
gridData = _gridData;
}*/
public Vector2 GridSize = Vector2.one;
public Vector2 startPoint;
public Vector2 endPoint;
public static Func<Vector2, bool> IsWalk;
public static Func<Vector2, Vector2, bool> IsObstacles;
/*
public APath(Func<Vector2, bool> isWalk, Func<Vector2, Vector2, bool> isObstacles)
{
IsWalk = isWalk;
IsObstacles = isObstacles;
}*/
public void SetStartPoint(Vector2 start)
{
startPoint = new Vector2((int)start.x, (int)start.y);
}
public void SetEndPoint(Vector2 end)
{
endPoint = new Vector2((int)end.x, (int)end.y);
}
/// <summary>
/// 获取路径
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public void GetPath(object state)
{
Actor actor = (Actor)state;
//初始化操作
//startPoint = new Vector2((int)start.x, (int)start.y);
//endPoint = new Vector2((int)end.x, (int)end.y);
APoint.Clear(ref Close);
APoint.Clear(ref Open);
//Close.Clear();
//Open.Clear();
APoint curPoint = APoint.Create();
curPoint.Point = startPoint;
curPoint.G = 0;
curPoint.H = 0;
if (curPoint == null)
Console.WriteLine("111");
do
{
if (Open.Contains(curPoint))
Open.Remove(curPoint);
Close.Add(curPoint);
if (IsEnd(curPoint))
break;
if (Open != null)
{
GetAround(curPoint);
APoint nextPoint = null;
float minF = -1;
for (int i = 0; i < Open.Count; i++)
{
//mimF == -1 表示F没有进行初始化,第一次循环进行初始化
//Debug.Log(string.Format("Point:{0} G:{1} H:{2} F:{3}", Open[i].Point, Open[i].G, Open[i].H, Open[i].F));
if (minF == -1)
{
minF = Open[i].F;
nextPoint = Open[i];
continue;
}
//获取F最小的点进行赋值
if (Open[i].F < minF)
{
minF = Open[i].F;
nextPoint = Open[i];
}
}
if (nextPoint == null)
Console.WriteLine("111111");
//清空open表
curPoint = nextPoint;
}
} while (Open.Count > 0);
List<Vector2> pointList = new List<Vector2>();
if (curPoint != null)
{
APoint prePoint = curPoint;
while (true)
{
if (prePoint.prePoint == null)
break;
pointList.Add(prePoint.Point);
prePoint = prePoint.prePoint;
}
}
MapPath.MainThreadAction.Push(delegate {
actor.OnFindPathFinshEvent(actor, ReversePoint(pointList));
OnFinsh();
});
}
/// <summary>
/// 反转列表
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public List<Vector2> ReversePoint(List<Vector2> point)
{
List<Vector2> newPoint = new List<Vector2>();
for (int i = point.Count - 1; i >= 0; i--)
newPoint.Add(point[i]);
return newPoint;
}
/// <summary>
/// 获取点周围数据
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
float x = 2f;
public void GetAround(APoint point)
{
//获取左右上下八个方位的点
Vector2 top = new Vector2(point.Point.x, point.Point.y + GridSize.y);
if (IsAddOpen(top, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = top;
apoint.G = point.G + 1;
apoint.H = GetH(top);
Open.Add(apoint);
}
Vector2 down = new Vector2(point.Point.x, point.Point.y - GridSize.y);
if (IsAddOpen(down, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = down;
apoint.G = point.G + 1;
apoint.H = GetH(down);
Open.Add(apoint);
}
Vector2 left = new Vector2(point.Point.x - GridSize.x, point.Point.y);
if (IsAddOpen(left, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = left;
apoint.G = point.G + 1;
apoint.H = GetH(left);
Open.Add(apoint);
}
Vector2 right = new Vector2(point.Point.x + GridSize.x, point.Point.y);
if (IsAddOpen(right, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = right;
apoint.G = point.G + 1;
apoint.H = GetH(right);
Open.Add(apoint);
}
Vector2 topLeft = new Vector2(point.Point.x - GridSize.x, point.Point.y + GridSize.y);
if (IsAddOpen(topLeft, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = topLeft;
apoint.G = point.G + x;
apoint.H = GetH(topLeft);
Open.Add(apoint);
}
Vector2 topRight = new Vector2(point.Point.x + GridSize.x, point.Point.y + GridSize.y);
if (IsAddOpen(topRight, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = topRight;
apoint.G = point.G + x;
apoint.H = GetH(topRight);
Open.Add(apoint);
}
Vector2 downLeft = new Vector2(point.Point.x - GridSize.x, point.Point.y - GridSize.y);
if (IsAddOpen(downLeft, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = downLeft;
apoint.G = point.G + x;
apoint.H = GetH(downLeft);
Open.Add(apoint);
}
Vector2 downRight = new Vector2(point.Point.x + GridSize.x, point.Point.y - GridSize.y);
if (IsAddOpen(downRight, IsWalk))
{
APoint apoint = APoint.Create();
apoint.prePoint = point;
apoint.Point = downRight;
apoint.G = point.G + x;
apoint.H = GetH(downRight);
Open.Add(apoint);
}
}
public int GetH(Vector2 point)
{
Vector2 offset = endPoint - point;
int H = (int)(Math.Abs(offset.x) + Math.Abs(offset.y));
return H;
}
public bool IsEnd(APoint point)
{
// 如果是结束为止 返回null、
if (point.Point.x == endPoint.x && point.Point.y == endPoint.y)
return true;
return false;
}
/// <summary>
/// 是否在关闭列表中
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public bool IsClose(Vector2 point)
{
for (int i = 0; i < Close.Count; i++)
{
if (Close[i].Point.x == point.x&&Close[i].Point.y==point.y)
return true;
}
return false;
}
/// <summary>
/// 是否在检测列表中
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public bool IsOpen(Vector2 point)
{
for (int i = 0; i < Open.Count; i++)
{
if (Open[i].Point.x == point.x && Open[i].Point.y == point.y)
return true;
}
return false;
}
/// <summary>
/// 是否添加进检测列表中
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public bool IsAddOpen(Vector2 point,Func<Vector2,bool> isWalk)
{
//可行走 不在关闭列表 不在打开列表
if (isWalk(point) && !IsClose(point) && !IsOpen(point))
{
return true;
}
return false;
}
public void OnFinsh()
{
Pool.Push(this);
}
}
public class APoint
{
private static Stack<APoint> Pool = new Stack<APoint>();
private APoint() { }
public Vector2 Point;
public APoint prePoint;
public float G; //到起点的距离
public int H; //到终点的距离
public float F //消耗
{
get
{
return G + H;
}
}
public void Close()
{
Point = Vector2.zero;
prePoint = null;
G = 0;
H = 0;
Pool.Push(this);
}
public static void Clear(ref List<APoint> aPoint)
{
for (int i = 0; i < aPoint.Count; i++)
aPoint[i].Close();
aPoint.Clear();
}
public static APoint Create()
{
if (Pool.Count < 1)
return new APoint();
return Pool.Pop();
}
}
此类初始话时,需要提供三个参数,玩家,其实目标和结束目标。
感觉这个东西只能自己研究看看,在真正的游戏项目中还没办法使用,因为,优化效果太差了,随便看看吧,过完年,在考虑怎么进行优化…
最终结果
寻路: 中间色块都用屎黄色进行标识,看不清楚我画了一条红线