Exemple #1
0
        /// <summary>
        /// 对角线估价法
        /// </summary>
        /// <param name="startAStarNodeData"></param>
        /// <param name="endAStarNodeData"></param>
        /// <param name="diagCost"></param>
        /// <param name="straightCost"></param>
        /// <returns></returns>
        public int Diagonal(AStarNodeData startAStarNodeData, AStarNodeData endAStarNodeData, int diagCost = 14, int straightCost = 10)
        {
            int dx       = Mathf.Abs(startAStarNodeData.x - endAStarNodeData.x);
            int dy       = Mathf.Abs(startAStarNodeData.y - endAStarNodeData.y);
            int diag     = Mathf.Min(dx, dy);
            int straight = dx + dy;

            return(diagCost * diag + straightCost * (straight - 2 * diag));
        }
Exemple #2
0
        public List <AStarNodeData> AStarFindPath(Vector3 start, Vector3 end)
        {
            AStarNodeData           startAStarNodeData = GetAStarNodeData(start);
            AStarNodeData           endAStarNodeData   = GetAStarNodeData(end);
            List <AStarNodeData>    openList           = new List <AStarNodeData>();    //等待检查列表
            HashSet <AStarNodeData> closeList          = new HashSet <AStarNodeData>(); //检查完成列表

            openList.Add(startAStarNodeData);
            while (openList.Count > 0)
            {
                AStarNodeData current = openList[0];
                for (int i = 0; i < openList.Count; i++)
                {
                    //等待检查列表里最短距离的节点
                    if (openList[i].FCost <= current.FCost && openList[i].hCost < current.hCost)
                    {
                        current = openList[i];
                    }
                }
                openList.Remove(current);
                closeList.Add(current);
                if (current == endAStarNodeData)
                {
                    return(GeneratePath(startAStarNodeData, endAStarNodeData));
                }
                foreach (AStarNodeData item in GetAStarNodeDataAround(current))
                {
                    if (item.isWall || closeList.Contains(item))
                    {
                        continue;
                    }
                    //计算与开始节点的距离
                    int gCost = current.gCost + GetAStarNodeDataDistance(current, item);
                    //如果不在等待检查列表中或者与开始节点的距离更小
                    if (!openList.Contains(item) || gCost < item.gCost)
                    {
                        //更新与开始节点的距离
                        item.gCost = gCost;
                        //更新与end节点的距离
                        item.hCost = GetAStarNodeDataDistance(item, endAStarNodeData);
                        //更新父节点为当前选定的节点
                        //在考查从一个节点移动到另一个节点时,总是拿自身节点周围的8个相邻节点来说事儿,相对于周边的节点来讲,自身节点称为它们的父节点.
                        item.parent = current;
                        if (!openList.Contains(item))
                        {
                            openList.Add(item);
                        }
                    }
                }
            }
            return(GeneratePath(startAStarNodeData, null));
        }
Exemple #3
0
        /// <summary>
        /// 取得周围的节点
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public List <AStarNodeData> GetAStarNodeDataAround(AStarNodeData data)
        {
            List <AStarNodeData> dataList = new List <AStarNodeData>();

            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    //自己
                    if (i == 0 && j == 0)
                    {
                        continue;
                    }
                    int x = data.x + i;
                    int y = data.y + j;
                    if (x < 0)
                    {
                        x = w - x;
                        if (!(x < w * 2 && x > w))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (!(x <= w && x >= 0))
                        {
                            continue;
                        }
                    }
                    if (y < 0)
                    {
                        y = h - y;
                        if (!(y < h * 2 && y > h))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (!(y <= h && y >= 0))
                        {
                            continue;
                        }
                    }
                    dataList.Add(aStarNodeDatas[x, y]);
                }
            }
            return(dataList);
        }
Exemple #4
0
        /// <summary>
        /// 生成路径
        /// </summary>
        /// <param name="startAStarNodeData"></param>
        /// <param name="endAStarNodeData"></param>
        /// <returns></returns>
        public List <AStarNodeData> GeneratePath(AStarNodeData startAStarNodeData, AStarNodeData endAStarNodeData)
        {
            List <AStarNodeData> pathList = new List <AStarNodeData>();

            if (endAStarNodeData != null)
            {
                AStarNodeData temp = endAStarNodeData;
                while (temp != startAStarNodeData)
                {
                    pathList.Add(temp);
                    temp = temp.parent;
                }
                pathList.Reverse();
            }
            UpdatePath(pathList.ToArray());
            return(pathList);
        }
Exemple #5
0
 /// <summary>
 /// 获取两个节点之间的距离
 /// </summary>
 /// <param name="startAStarNodeData"></param>
 /// <param name="endAStarNodeData"></param>
 /// <returns></returns>
 public int GetAStarNodeDataDistance(AStarNodeData startAStarNodeData, AStarNodeData endAStarNodeData)
 {
     return(Diagonal(startAStarNodeData, endAStarNodeData));
 }
Exemple #6
0
        public void InitManager(float radius, LayerMask layer, bool isShowWall, bool isShowPath, GameObject gameObject, float ratio = 1)
        {
            this.radius     = radius;
            this.layer      = layer;
            this.isShowWall = isShowWall;
            this.isShowPath = isShowPath;

            w = Mathf.RoundToInt(gameObject.GetComponent <BoxCollider2D>().bounds.size.x *ratio);
            h = Mathf.RoundToInt(gameObject.GetComponent <BoxCollider2D>().bounds.size.y *ratio);
            aStarNodeDatas = new AStarNodeData[w * 2, h * 2];
            wall           = new GameObject("Wall").transform;
            path           = new GameObject("Path").transform;
            //将墙的信息写入格子中
            for (int x = 0; x <= w; x++)
            {
                for (int y = 0; y <= h; y++)
                {
                    Vector3 localPosition = new Vector3(x * 0.5f, y * 0.5f, 0);
                    //通过节点中心发射圆形射线,检测当前位置是否可以行走
                    bool wall = false;
                    //wall = Physics.CheckSphere(localPosition, radius, layer); 3D
                    Collider2D[] colliders = Physics2D.OverlapCircleAll(localPosition, radius, layer);
                    if (colliders.Length > 0)
                    {
                        wall = true;
                    }
                    aStarNodeDatas[x, y] = new AStarNodeData(wall, localPosition, x, y);
                    if (wall)
                    {
                        //InitWallGrid(localPosition, isShowWall);
                    }
                }
            }
            for (int x = -w + 1; x < 0; x++)
            {
                for (int y = 0; y <= h; y++)
                {
                    Vector3      localPosition = new Vector3(x * 0.5f, y * 0.5f, 0);
                    bool         wall          = false;
                    Collider2D[] colliders     = Physics2D.OverlapCircleAll(localPosition, radius, layer);
                    if (colliders.Length > 0)
                    {
                        wall = true;
                    }
                    aStarNodeDatas[w - x, y] = new AStarNodeData(wall, localPosition, x, y);
                    if (wall)
                    {
                        //InitWallGrid(localPosition, isShowWall);
                    }
                }
            }
            for (int x = 0; x <= w; x++)
            {
                for (int y = -h + 1; y < 0; y++)
                {
                    Vector3      localPosition = new Vector3(x * 0.5f, y * 0.5f, 0);
                    bool         wall          = false;
                    Collider2D[] colliders     = Physics2D.OverlapCircleAll(localPosition, radius, layer);
                    if (colliders.Length > 0)
                    {
                        wall = true;
                    }
                    aStarNodeDatas[x, h - y] = new AStarNodeData(wall, localPosition, x, y);
                    if (wall)
                    {
                        //InitWallGrid(localPosition, isShowWall);
                    }
                }
            }
            for (int x = -w + 1; x < 0; x++)
            {
                for (int y = -h + 1; y < 0; y++)
                {
                    Vector3      localPosition = new Vector3(x * 0.5f, y * 0.5f, 0);
                    bool         wall          = false;
                    Collider2D[] colliders     = Physics2D.OverlapCircleAll(localPosition, radius, layer);
                    if (colliders.Length > 0)
                    {
                        wall = true;
                    }
                    aStarNodeDatas[w - x, h - y] = new AStarNodeData(wall, localPosition, x, y);
                    if (wall)
                    {
                        //InitWallGrid(localPosition, isShowWall);
                    }
                }
            }
        }