Unity游戏开发AI-A*寻路算法

Unity3d利用A*寻路算法实现寻路模拟

https://blog.csdn.net/qq_33747722/article/details/78436919

【Unity】【C#】A*寻路算法-学习心得

https://blog.csdn.net/Terrell21/article/details/82584634

自己实现效果

设置point点

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Point
{

    public Point Parent { get; set; }//父
    public float F { get; set; }
    public float G { get; set; }
    public float H { get; set; }


    public int X { get; set; }
    public int Y { get; set; }
    /// <summary>
    /// 是否是障碍物
    /// </summary>
    public bool IsWall { get; set; }
    /// <summary>
    /// 构造 初始化
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="parent"></param>
    public Point(int x, int y, Point parent = null)
    {
        this.X = x;
        this.Y = y;
        this.Parent = parent;
        this.IsWall = false;
    }

    /// <summary>
    /// 更新父亲
    /// </summary>
    /// <param name="parent"></param>
    /// <param name="g"></param>
    public void UpdateParent(Point parent, float g)
    {
        this.Parent = parent;
        this.G = g;
        this.F = G + H;

    }
}

A*寻路算法实现

using System.Collections.Generic;
using UnityEngine;

public class AStart : MonoBehaviour
{


    private const int mapWhith = 8;
    private const int mapHight = 6;
    private Point[,] map = new Point[mapWhith, mapHight];//二维数组



    // Use this for initialization
    void Start()
    {
        InitMap();
        Point start = map[2, 3];//开始点
        Point end = map[6, 3];//结束点
        FindPath(start, end);
        ShowPath(start, end);
        //List<Point> l = GetSurroundPoints(new Point(3, 3));
        //foreach (var item in l)
        //{
        //    Debug.Log(item.X + "-" + item.Y);
        //}
    }
    /// <summary>
    /// 构建虚拟地图
    /// </summary>
    private void InitMap()
    {
        for (int x = 0; x < mapWhith; x++)
        {
            for (int y = 0; y < mapHight; y++)
            {
                map[x, y] = new Point(x, y);
            }
        }
        //设置障碍物
        map[4, 2].IsWall = true;
        map[4, 3].IsWall = true;
        map[4, 4].IsWall = true;

    }



    /// <summary>
    /// 现实路径
    /// </summary>
    /// <param name="start"></param>
    /// <param name="end"></param>
    public void ShowPath(Point start, Point end)
    {
        Point temp = end;
        while (true)
        {
            Debug.Log(temp.X + "--" + temp.Y);

            CreateCube(temp.X, temp.Y, Color.red);
            if (temp.Parent == null)
            {
                break;
            }
            temp = temp.Parent;
        }

        for (int x = 0; x < mapWhith; x++)
        {
            for (int y = 0; y < mapHight; y++)
            {
                if (map[x, y].IsWall == true)
                {
                    CreateCube(x, y, Color.gray);
                }
            }
        }

    }

    public void CreateCube(float x, float y, Color color)
    {
        GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
        go.transform.position = new Vector3(x, y, 0);
        go.GetComponent<MeshRenderer>().material.color = color;
    }
    /// <summary>
    ///  路径的计算
    /// </summary>
    /// <param name="start">开始点</param>
    /// <param name="end">结束点</param>
    private void FindPath(Point start, Point end)
    {
        List<Point> openList = new List<Point>();//开始集合
        List<Point> closeList = new List<Point>();//关闭集合
        openList.Add(start);                      //将开始点加入集合

        ///这个while有两个终止条件 1,openlist为空  2, 找到目标位置
        //在开集合找到距离最短的点  F最小
        while (openList.Count > 0)
        {
            Point point = FindMinFPoint(openList);//找到最小的F
            openList.Remove(point);             //在开集合中移除
            closeList.Add(point);               //在关集合中添加
            List<Point> surroundPoints = GetSurroundPoints(point);//得到周围点的集合
            PointsFilter(surroundPoints, closeList);//检查集合是否在闭 在关闭列表就不往开启列表添加数据了
            foreach (Point surroundPoint in surroundPoints)
            {
                if (openList.IndexOf(surroundPoint) > -1)
                {
                    float nowG = CalcG(surroundPoint, point);//更新G值,加上父的G值
                    if (nowG < surroundPoint.G)
                    {
                        surroundPoint.UpdateParent(point, nowG);//更新父亲
                    }
                }
                else
                {
                    surroundPoint.Parent = point;//设置父亲
                    CalcF(surroundPoint, end);//计算F值
                    openList.Add(surroundPoint);//加入开集合
                }
            }
            // 判断结束条件  判断end 是否在结束列表中 
            if (openList.IndexOf(end) > -1)
            {
                break;
            }

        }
    }

    /// <summary>
    /// 检查集合是否在关闭列表中 (目的)如果 在关闭列表就不往开启列表添加数据了
    /// </summary>
    /// <param name="src"> 需要检查的集合</param>
    /// <param name="closePoint">  已经加入关闭列表的集合</param>
    /// <returns></returns>
    private void PointsFilter(List<Point> src, List<Point> closePoint)
    {
        foreach (Point p in closePoint)
        {
            if (src.IndexOf(p) > -1)//若p不存在,返回-1   src.IndexOf(p) > -1
            {
                src.Remove(p);
            }
        }
    }

    /// <summary>
    /// 返回一个点附近的点的集合
    /// </summary>
    /// <param name="point"></param>
    /// <returns></returns>
    public List<Point> GetSurroundPoints(Point point)
    {
        Point up = null, down = null, left = null, right = null;
        Point lu = null, ru = null, ld = null, rd = null;
        //上、下
        if (point.Y < mapHight - 1)        //边界判断,
        {
            up = map[point.X, point.Y + 1];
        }
        if (point.Y > 0)
        {
            down = map[point.X, point.Y - 1];
        }
        //左、右
        if (point.X > 0)
        {
            left = map[point.X - 1, point.Y];
        }
        if (point.X < mapWhith - 1)
        {
            right = map[point.X + 1, point.Y];
        }
        //左上、右上
        if (up != null && left != null)
        {
            lu = map[point.X - 1, point.Y + 1];
        }
        if (up != null && right != null)
        {
            ru = map[point.X + 1, point.Y + 1];
        }
        //左下,右下
        if (down != null && left != null)
        {
            ld = map[point.X - 1, point.Y - 1];
        }
        if (down != null && right != null)
        {
            rd = map[point.X + 1, point.Y - 1];
        }
        //将可到达的点加入集合
        List<Point> list = new List<Point>();
        //上下左右
        if (down != null && down.IsWall == false)
        {
            list.Add(down);
        }
        if (up != null && up.IsWall == false)
        {
            list.Add(up);
        }
        if (left != null && left.IsWall == false)
        {
            list.Add(left);
        }
        if (right != null && right.IsWall == false)
        {
            list.Add(right);
        }
        //四个斜角
        if (lu != null && lu.IsWall == false && left.IsWall == false && up.IsWall == false)
        {
            list.Add(lu);
        }
        if (ld != null && ld.IsWall == false && left.IsWall == false && down.IsWall == false)
        {
            list.Add(ld);
        }
        if (ru != null && ru.IsWall == false && right.IsWall == false && up.IsWall == false)
        {
            list.Add(ru);
        }
        if (rd != null && rd.IsWall == false && right.IsWall == false && down.IsWall == false)
        {
            list.Add(rd);
        }
        return list;

    }

    /// <summary>
    /// 找寻Point最小的F值
    /// </summary>
    /// <param name="openList"></param>
    /// <returns></returns>
    private Point FindMinFPoint(List<Point> openList)
    {
        float f = float.MaxValue;//设置最大值
        Point temp = null;
        foreach (Point p in openList)
        {
            if (p.F < f)
            {
                temp = p;
                f = p.F;
            }
        }
        return temp;
    }
    /// <summary>
    /// 计算G值
    /// </summary>
    /// <param name="now"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    public float CalcG(Point now, Point parent)
    {
        return Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(parent.X, parent.Y)) + parent.G;
    }

    /// <summary>
    /// 计算F值
    /// </summary>
    /// <param name="now"></param>
    /// <param name="end"></param>
    private void CalcF(Point now, Point end)
    {
        // F  =  G  +  H 
        // 求得F值
        float h = Mathf.Abs(end.X - now.X) + Mathf.Abs(end.Y - now.Y);
        //预计到达目标点的距离
        float g = 0;
        if (now.Parent == null)//即为开始点
        {
            g = 0;
        }
        else
        {
            g = Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(now.Parent.X, now.Parent.Y)) + now.Parent.G;
        }

        float f = g + h;
        now.F = f;
        now.G = g;
        now.H = h;

    }
}

最终效果

 

猜你喜欢

转载自blog.csdn.net/qq_35422344/article/details/86522941