更新日期:2019年12月30日。
Github源码:[点我获取源码]
A*寻路简介
常规的A*寻路算法,目前支持两点间寻路,或只提供起点后根据行走值寻所有可行走节点。
使用A*寻路
生成寻路网格
在任意物体上添加AStarGrid脚本,此为A*寻路的核心脚本。
AStarGrid属性面板:
1.Evaluation Type:估价算法类型,默认采用AStarManhattan(曼哈顿估价算法)。
2.Size:寻路网格尺寸。
3.Node Radius:单个节点半径。
4.Ignore Oblique:寻路计算时,忽略对角节点。
5.Auto Generate:自动生成寻路网格,也就是省略本文的下一步。
也可以在其他位置初始化的时候生成寻路网格。
private AStarGrid _aStarGrid;
//生成网格
_aStarGrid.GenerateGrid();
自定义寻路规则
您可以自定义寻路规则,用来处理每一个寻路网格中的节点,比如标记某个节点为不可行走,提升某个节点的自身估价,当角色妄图走过该节点时,它会付出更多的代价(这主要用于寻可行走节点)。
如下,我们自定义一个规则,将横向(X)第5行的第2列到第8列之间设置为不可行走的障碍。
public class AStarTestRule : AStarRule
{
public override void Apply(AStarNode node)
{
if (node.XIndex == 5 && node.YIndex > 2 && node.YIndex < 8)
{
node.IsCanWalk = false;
}
}
}
两点间寻路
寻路网格生成之后便可以直接寻路,我们调用如下接口寻路:
/// <summary>
/// 寻路
/// </summary>
/// <param name="startPoint">起点</param>
/// <param name="endPoint">终点</param>
/// <param name="rule">搜寻规则</param>
/// <returns>结果路径</returns>
public List<AStarNode> Pathfinding(Vector3 startPoint, Vector3 endPoint, AStarRule rule = null)
如下,我们新建一个测试流程,键入代码:
/// <summary>
/// A*流程
/// </summary>
public class AStarProcedure : ProcedureBase
{
private AStarGrid _aStarGrid;
private AStarTestRule _rule;
private Transform _startPoint;
private Transform _endPoint;
/// <summary>
/// 流程初始化
/// </summary>
public override void OnInit()
{
_aStarGrid = GameObject.Find("AStarGrid").GetComponent<AStarGrid>();
_rule = new AStarTestRule();
_startPoint = GameObject.Find("StartPoint").transform;
_endPoint = GameObject.Find("EndPoint").transform;
//生成网格
_aStarGrid.GenerateGrid();
}
/// <summary>
/// 流程帧刷新
/// </summary>
public override void OnUpdate()
{
//按下 空格 寻路
if (Input.GetKeyDown(KeyCode.Space))
{
_aStarGrid.Pathfinding(_startPoint.position, _endPoint.position, _rule);
}
//按下 回车 寻可行走节点
if (Input.GetKeyDown(KeyCode.Return))
{
_aStarGrid.WalkableNodefinding(_startPoint.position, 5, _rule);
}
}
}
我们运行场景,按下空格寻路:
图中的两个球形为起点和终点,寻路完成后青色的方块为最终路径,红色的方块为障碍物,不可行走。
寻可行走节点
寻可行走节点的功能可以用于部分横版网格回合制游戏,每一回合,每一个角色根据其行走速度,可以在地图上罗列出所有可以行走的终点。
注意:寻可行走节点的功能理论上应用于将地图划分为标准网格的场景,所以在搜寻时会自动忽略对角网格。
我们重新定义一下寻路规则:
public class AStarTestRule : AStarRule
{
public override void Apply(AStarNode node)
{
if (node.XIndex == 5 && node.YIndex > 2 && node.YIndex < 8)
{
//提高节点的估价,在某些游戏中,这类节点往往是高山或者湖泊,玩家想要走过去,自然会花费更大的代价
node.OCost = 1;
}
}
}
开始寻可行走节点:
//以 _startPoint.position 为起点寻可行走路径,角色的行走速度为10
_aStarGrid.WalkableNodefinding(_startPoint.position, 10, _rule);
如上图,红框标记的五个节点为高价值节点,角色在经过这些高价值节点时,会降低自身的行走速度,具体根据该节点的价值而定。
我们将角色行走速度改为3:
//以 _startPoint.position 为起点寻可行走路径,角色的行走速度为3
_aStarGrid.WalkableNodefinding(_startPoint.position, 3, _rule);
可以看到,在经过红框的高价值节点【高山】时,角色行走速度为3的情况下只能穿过【高山】抵达另一边的一个节点,在【高山】上往下行走是不行的,因为高山节点的价值为1(常规节点为0),相当于两个常规节点,角色走过需要花费两倍的代价,也就是说必须要速度4才能通过,所以这些都不是本回合的可行走节点。