A*寻路算法

         需要设置地图尺寸,设置绘制路点物体,

        基于判断周围物体的碰撞体来识别障碍,

        在别的脚本中调用AStarSearchPath(Vector3 startPos, Vector3 endPos)方法即可

using System.Collections.Generic;
using UnityEngine;

public class AStar : MonoBehaviour
{
    //开启列表(任务列表),存储当前节点,父节点
    private Dictionary<Vector2Int, Vector2Int> openDic = new Dictionary<Vector2Int, Vector2Int>();
    //关闭列表(查询过的点不再查询)
    private List<Vector2Int> closeList = new List<Vector2Int>();
    //g是父节点步长加上当前节点步长所得,累加
    private Dictionary<Vector2Int, float> costDic  = new Dictionary<Vector2Int, float>();
    //h是当前节点到终点的消耗,计算所得,值固定
    private Dictionary<Vector2Int, float> heuristicDic = new Dictionary<Vector2Int, float>();

    //A*算法主函数
    public List<Vector2Int> AStarSearchPath(Vector2Int startPos,Vector2Int endPos)
    {
        //初始化
        openDic.Clear();
        closeList.Clear();
        costDic.Clear();
        heuristicDic.Clear();
        heuristicDic.Add(startPos, GetHeuristic(startPos, endPos));
        costDic.Add(startPos, 0);
        openDic.Add(startPos,startPos);
        closeList.Add(startPos);
        while (costDic.Count > 0)
        {
            //在openList列表中找出F最小的点
            Vector2Int current = GetShortestPos();
            if (current.Equals(endPos))
                break;
            //计算当前节点的相邻节点
            List<Vector2Int> neighbors = GetNeighbors(current);
            //循环邻居
            foreach(Vector2Int next in neighbors)
            {
                //如果对象不存在与closeList列表中
                if (!closeList.Contains(next))
                {
                    //难点!!!
                    costDic.Add(next, costDic[current] + GetCost(current, next));
                    heuristicDic.Add(next, costDic[next] + GetHeuristic(next, endPos));
                    openDic.Add(next, current);
                    closeList.Add(next);
                }
            }
        }
        List<Vector2Int> pathList = ShowPath(startPos, endPos);
        pathList.Reverse(); //翻转,排序正确
        return pathList;
    }

    public int mapSize;
    //获得相邻点
    private List<Vector2Int> GetNeighbors(Vector2Int point)
    {
        Vector2Int up = point + Vector2Int.up;
        Vector2Int down = point + Vector2Int.down;
        Vector2Int left = point + Vector2Int.left;
        Vector2Int right = point + Vector2Int.right;
        Vector2Int upleft = point + Vector2Int.up + Vector2Int.left;
        Vector2Int upright = point + Vector2Int.up + Vector2Int.right;
        Vector2Int downleft = point + Vector2Int.down + Vector2Int.left;
        Vector2Int downright = point + Vector2Int.down + Vector2Int.right;
        List<Vector2Int> neighbourList = new List<Vector2Int>();
        if (up.y < mapSize && !Physics2D.OverlapCircle(up, 0.1f))
            neighbourList.Add(up);
        if (down.y >= 0 && !Physics2D.OverlapCircle(down, 0.1f))
            neighbourList.Add(down);
        if (left.x >= 0 && !Physics2D.OverlapCircle(left, 0.1f))
            neighbourList.Add(left);
        if (right.x < mapSize && !Physics2D.OverlapCircle(right, 0.1f))
            neighbourList.Add(right);
        if (upleft.x > 0 && upleft.y < mapSize 
            && !Physics2D.OverlapCircle(upleft, 0.1f))
            neighbourList.Add(upleft);
        if (upright.x < mapSize && upright.y < mapSize
            && !Physics2D.OverlapCircle(upright, 0.1f))
            neighbourList.Add(upright);
        if (downleft.x > 0 && downleft.y > 0 
            && !Physics2D.OverlapCircle(downleft, 0.1f))
            neighbourList.Add(downleft);
        if (downright.x < mapSize && downright.y > 0 
            && !Physics2D.OverlapCircle(downright, 0.1f))
            neighbourList.Add(downright);
        return neighbourList;
    }

    //获取当前点到相邻点的步长,1或1.4
    private float GetCost(Vector2Int current, Vector2Int next)
    {
        if (Mathf.Abs(current.x - next.x) == 1 && Mathf.Abs(current.y - next.y) == 1)
            return 1.4f;
        else
            return 1;
    }

    //获取当前位置到终点的消耗(距离)
    private float GetHeuristic(Vector2Int posA, Vector2Int posB)
    {
        return Mathf.Abs(posA.x - posB.x) + Mathf.Abs(posA.y - posB.y);
    }

    //获取任务(开启)列表openList里最少消耗的坐标
    private Vector2Int GetShortestPos()
    {
        //定义一个键值对,初始化
        KeyValuePair<Vector2Int, float> shortest = 
            new KeyValuePair<Vector2Int, float>(Vector2Int.zero, int.MaxValue);
        foreach(var item in heuristicDic)
            if(item.Value < shortest.Value)
                shortest = item;
        heuristicDic.Remove(shortest.Key);
        return shortest.Key;
    }

    //画路径
    public GameObject pathImage;
    private List<Vector2Int> ShowPath(Vector2Int startPos, Vector2Int endPos)
    {
        List<Vector2Int> pathList = new List<Vector2Int>();
        Vector2Int current = endPos;
        pathList.Add(current);
        while (current != startPos)
        {
            Vector2Int next = openDic[current];
            pathList.Add(next);
            current = next;
        }
        return pathList;
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值