unity中使用A*算法寻路典例

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//传说中的最优寻路方法,A*
public class Navigation : MonoBehaviour
{
private Vector2 chushiposition;
public GameObject gametest;
public GameObject gametestlujing;
[Range(0.5f, 1f)]
public float lengthofbox;//我的tilemap每个格子是1所以我设置的是1,这个可以根据实际情况改
public LayerMask NodeLayer;//选择障碍物所在的层
public Transform player;//拖上目标对象(被追踪者)
private Transform startPos;
public Transform meshOrigin;//格子起点对象
public class NodeItem
{//单位格子类
public bool iswall;
public Vector2 worldpos;
public int x, y;
public int g;
public int h;
public int f
{
get { return g + h; }
}
public NodeItem parentNode;
public NodeItem(bool iswall, Vector2 worldpos, int x, int y)
{
this.iswall = iswall;
this.worldpos = worldpos;
this.x = x;
this.y = y;
}
}
private NodeItem[,] nodeItems;
private int w, h;
private void Awake()
{//初始化所有格子
chushiposition = this.transform.position;
w = 40; h = 40;
nodeItems = new NodeItem[w, h];
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
Vector2 pos = new Vector2(i * lengthofbox, j * lengthofbox) + (Vector2)meshOrigin.position;
bool iswall = false;
// bool iswall = Physics2D.BoxCast(pos, new Vector2(lengthofbox-0.5f, lengthofbox-0.5f), 0, new Vector2(0, 0), NodeLayer);
RaycastHit2D hit = Physics2D.BoxCast(pos, new Vector2(lengthofbox - 0.5f, lengthofbox - 0.5f), 0, new Vector2(0, 0), NodeLayer);
if (hit)
{
iswall = true;
if (hit.collider.gameObject.tag == "Player" || hit.collider.gameObject.tag == "guai")
{
iswall = false;
}
}
nodeItems[i, j] = new NodeItem(iswall, pos, i, j);
//if (nodeItems[i, j].iswall)
//{
// GameObject.Instantiate(gametest, nodeItems[i, j].worldpos,Quaternion.identity);
//}
}
}
}
private void Start()
{
startPos = this.transform;
}
public NodeItem GetIdem(Vector2 pos)
{//获取坐标的格子坐标
int i = Mathf.RoundToInt((pos.x - ((Vector2)meshOrigin.position).x) / lengthofbox);
int j = Mathf.RoundToInt((pos.y - ((Vector2)meshOrigin.position).y) / lengthofbox);
i = Mathf.Clamp(i, 0, w - 1);
j = Mathf.Clamp(j, 0, h - 1);
return nodeItems[i, j];
}
public List<NodeItem> Idemaround(NodeItem node)
{//获取周围8个格子信息
List<NodeItem> aroundlist = new List<NodeItem>();
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i != 0 || j != 0)
{
int x = node.x + i;
int y = node.y + j;
if (x < w && x >= 0 && y < h && y >= 0)
{
aroundlist.Add(nodeItems[node.x + i, node.y + j]);
}
}
}
}
// for(int c = 0; c < aroundlist.Count; c++)
// {
// print(aroundlist[c].x + " " + aroundlist[c].y);
// }
return aroundlist;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.B))
{
findingpath((Vector2)startPos.position, (Vector2)player.position);
}
}
private void findingpath(Vector2 startpos, Vector2 distpos)
{//寻路
NodeItem startnode = GetIdem(startpos);
NodeItem distnode = GetIdem(distpos);
List<NodeItem> Openlist = new List<NodeItem>();
HashSet<NodeItem> Closelist = new HashSet<NodeItem>();
Openlist.Add(startnode);
while (Openlist.Count > 0)
{
NodeItem current = Openlist[0];
for (int i = 0, max = Openlist.Count; i < max; i++)
{
// print(Openlist[i].x + " " + Openlist[i].y + " " + Openlist[i].f);
if (current.f >= Openlist[i].f && current.h > Openlist[i].h)
{
current = Openlist[i];
}
}
Openlist.Remove(current);
Closelist.Add(current);
//Openlist.Clear();
if (current == distnode)
{
generatepath(startnode, distnode);
return;
}
foreach (NodeItem item in Idemaround(current))
{
if (item.iswall == false)
{
GameObject.Instantiate(gametest, item.worldpos, Quaternion.identity);
}
//print(item.x + " " + item.y + " " + item.f);
if (item.iswall || Closelist.Contains(item)) continue;
int newcost = current.g + getdistance(current, item);
if (newcost < item.g || !Openlist.Contains(item))
{
item.g = newcost;
item.h = getdistance(item, distnode);
item.parentNode = current;
if (!Openlist.Contains(item))
{
Openlist.Add(item);
}
}
}
}
generatepath(startnode, null);
}
private void generatepath(NodeItem A, NodeItem B)
{//生成路径泛型队列
List<NodeItem> path = new List<NodeItem>(http://www.amjmh.com/v/BIBRGZ_558768/);
if (B != null)
{
NodeItem node = B;
while (node != A)
{
path.Add(node);
node = node.parentNode;
}
path.Add(A);
path.Reverse();
print(path.Count);
for(int i = 0; i < path.Count; i++)
{
GameObject.Instantiate(gametestlujing, path[i].worldpos, Quaternion.identity);
}
}
}
private int getdistance(NodeItem curr, NodeItem item)
{//估算权值,对角线算法
//int costx = Mathf.Abs(curr.x - item.x);
//int costy = Mathf.Abs(curr.y - item.y);
//if (costx > costy)
//{
// return 10 * costx ;
//}
//else
//{
// return 10 *costy;
//}
//曼哈顿算法
return Mathf.Abs(curr.x - item.x) * 10 + Mathf.Abs(curr.y - item.y) * 10;
}
}

posted @ 2019-09-04 17:14  李艳艳665  阅读(574)  评论(0编辑  收藏  举报