下面是一个基本的Unity AStar寻路代码模板:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AStar : MonoBehaviour
{
// 节点类
public class Node
{
public int x; // x坐标
public int y; // y坐标
public bool walkable; // 是否可走
public Node parent; // 父节点
public int gCost; // 从起点到该节点的成本
public int hCost; // 从该节点到终点的估算成本
public int fCost // fCost = gCost + hCost
public Node(int x, int y, bool walkable)
{
this.x = x;
this.y = y;
this.walkable = walkable;
}
public int GetFCost()
{
return gCost + hCost;
}
}
public Node[,] grid; // 地图
public int gridSizeX; // 地图宽度
public int gridSizeY; // 地图高度
public Transform start; // 起点
public Transform end; // 终点
private List<Node> openList; // 开放列表
private List<Node> closedList; // 封闭列表
// 启动寻路
public void StartPathfinding()
{
openList = new List<Node>();
closedList = new List<Node>();
Node startNode = GetNodeFromPosition(start.position);
Node endNode = GetNodeFromPosition(end.position);
openList.Add(startNode);
while (openList.Count > 0)
{
Node currentNode = GetLowestFCostNode(openList);
if (currentNode == endNode)
{
// 找到终点,生成路径
List<Node> path = GeneratePath(startNode, endNode);
// TODO: 处理路径
return;
}
openList.Remove(currentNode);
closedList.Add(currentNode);
foreach (Node neighborNode in GetNeighborNodes(currentNode))
{
if (!neighborNode.walkable || closedList.Contains(neighborNode))
{
// 忽略不可走节点或已在封闭列表中的节点
continue;
}
int tentativeGCost = currentNode.gCost + GetDistance(currentNode, neighborNode);
if (tentativeGCost < neighborNode.gCost || !openList.Contains(neighborNode))
{
neighborNode.parent = currentNode;
neighborNode.gCost = tentativeGCost;
neighborNode.hCost = GetDistance(neighborNode, endNode);
if (!openList.Contains(neighborNode))
{
openList.Add(neighborNode);
}
}
}
}
// 无法到达终点
// TODO: 处理无法到达终点的情况
}
// 根据坐标获取节点
private Node GetNode(int x, int y)
{
if (x >= 0 && x < gridSizeX && y >= 0 && y < gridSizeY)
{
return grid[x, y];
}
else
{
return null;
}
}
// 根据位置获取节点
private Node GetNodeFromPosition(Vector3 position)
{
int x = Mathf.RoundToInt(position.x);
int y = Mathf.RoundToInt(position.z);
return GetNode(x, y);
}
// 获取相邻节点
private List<Node> GetNeighborNodes(Node node)
{
List<Node> neighborNodes = new List<Node>();
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (x == 0 && y == 0)
{
// 忽略自身节点
continue;
}
int checkX = node.x + x;
int checkY = node.y + y;
Node neighborNode = GetNode(checkX, checkY);
if (neighborNode != null)
{
neighborNodes.Add(neighborNode);
}
}
}
return neighborNodes;
}
// 获取两个节点之间的距离
private int GetDistance(Node nodeA, Node nodeB)
{
int distanceX = Mathf.Abs(nodeA.x - nodeB.x);
int distanceY = Mathf.Abs(nodeA.y - nodeB.y);
if (distanceX > distanceY)
{
return 14 * distanceY + 10 * (distanceX - distanceY);
}
else
{
return 14 * distanceX + 10 * (distanceY - distanceX);
}
}
// 获取开放列表中fCost最小的节点
private Node GetLowestFCostNode(List<Node> nodeList)
{
Node lowestFCostNode = nodeList[0];
for (int i = 1; i < nodeList.Count; i++)
{
if (nodeList[i].fCost < lowestFCostNode.fCost)
{
lowestFCostNode = nodeList[i];
}
}
return lowestFCostNode;
}
// 生成路径
private List<Node> GeneratePath(Node startNode, Node endNode)
{
List<Node> path = new List<Node>();
Node currentNode = endNode;
while (currentNode != startNode)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
path.Reverse();
return path;
}
}
使用时,需要在场景中创建一个空物体,将上面的代码作为其组件,并设置相应的参数,如地图大小、起点和终点位置等。然后,调用`StartPathfinding`方法启动寻路即可。