在Unity中实现Astar寻路算法

在游戏中,从一点到另一点的操作有时需要游戏系统自动完成,在一些带有rpg元素的游戏中,敌人在发现玩家位置后会自动向玩家的位置移动。这些移动的路线是如何自动确定的?本文将介绍寻路算法中的A*算法,并在unity中用C#脚本来实现寻路功能。

问题描述

现在有两个点:起点A,和终点B,允许向周围的八个方向移动,如图所示。需要找到从起点A到终点B效率最高的路径。
红色为起点,绿色为终点
当不存在任何障碍物时,找到两点之间的最短路径似乎毫无难度:只需要每一步都选择离目标点最近的邻近点即可。
在这里插入图片描述
但是当存在障碍物时,路径上的点与目标点的距离并不是单调变化的,这时如何用一个普适性的思路来找出最优路径?

算法思路

从数据结构的角度来看,网格化的地图是一种带有权值的无向图,而路径可以被视为由图中的结点组成的链表。因此,寻路的实质是在有权的图中,在所有以起点为头结点,终点为尾结点的链表中,选择长度最短的链表

核心思想

A*算法的核心思想是:使图中的每一个结点都处在使其权值最小的那条路径上。

权值的定义

首先,需要确定权值,或者叫代价(cost)的计算方式。点在路径上的代价由两部分组成:从起点到该点的代价从该点到终点的代价

1.从起点到该点的代价
从起点起到该点的代价应当为每一步新增的代价的总和。每向正上、下、左、右方向走一步,代价增加10,每斜向走一步,代价增加14;
在这里插入图片描述

2.从该点到终点的代价
从该点到终点的代价是用来估量这个点到终点还需要的过程长短,可以用该点到目标点的直线距离*10来表示。

搜索过程

依照这个想法,由于每走一步只能移动至8邻域,所以每个点的前置结点必然是其8邻域中的一个。只要对其8邻域的每个点作为前置节点时的最小代价进行比较,选择代价最小的点作为前置结点,依此迭代至终点,再向上提取前置就可以得到最优路径。

那对如何确定所有点的搜索顺序呢?因为仍然需要优先考虑朝终点最近的点,所以依然以点的总代价作为搜索顺序的依据,总代价小的优先被搜索(因为代价最小的点意味着已经处于最优路径)。

总结以上讨论,可以整理出出一个思路:

设置一个待搜索结点的集合open。从起点开始,每搜索到一个点,就以其作为前置结点,计算其所有邻近点在该路径上的代价,并与邻近点已有的前置结点下的代价比较,如果当前点带来的代价更小,则更新前置结点,并使所有邻近点放入待搜索集合open。将该点移除集合open。再在open中选取代价最小的结点,重复以上操作,直至搜索到终点。

当第一次搜索到终点时,此时路径第一次被完成,即为最优路径。
在这里插入图片描述

代码实现

Unity中实现A*算法的代码如下所示。这里将路径和待搜索点集合都用List类来表示;编写结点类Node,存放位置、代价和前置结点,其中起点对应的结点前置节点为null。

    //事先初始化的全局变量
    Vector2 origin, destination;//起点和终点
    int mapWidth, mapHeigth;//地图大小
    bool[,] isBarrier;//判断是否为路障
    List<Node> road;//路径存储
    void Astar()
    {
   
    	List<Node> open = new List<Node>();//待搜索的点
		List<Node> close = new List<Node>();//已经搜索过一次或多次的点
    	Node current;
        int minLocation;
        float min;
        //开始搜索
        open.
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值