Exemple #1
0
        /// <summary>
        /// 목적지에서 가까운 갈수있는 타일을 찾는다.
        /// </summary>
        /// <param name="unit">목적지에 가는 주체</param>
        /// <param name="dest">목적지</param>
        /// <returns></returns>
        public static Tile GetClosestReachableDest(Unit unit, Vector2Int dest)
        {
            Tile curTile = FieldManager.GetTileClamp(dest);

            List <Tile> frontier = new List <Tile>()
            {
                curTile
            };
            List <Tile> visited = new List <Tile>();

            Vector2Int [] directions = { Vector2Int.up, Vector2Int.down, Vector2Int.right, Vector2Int.left };

            int loop_count = 0;

            while (true)
            {
                InfiniteLoopDebug.Run("Pathfind", "GetClosestReachableDest", 140);
                // 무한루프 방지용
                loop_count++;
                if (frontier.Count == 0 || loop_count > 1000)
                {
                    Debug.Log("갈수 없거나 계산이 너무 오래걸립니다!");
                    return(null);
                }

                curTile = frontier[0];
                visited.Add(curTile);
                frontier.RemoveAt(0);

                // if (curTile.IsPositionable(unit))
                if (PathFindAlgorithm(/*unit,*/ unit.MoveSkill, unit.Position, curTile.position) != null)
                {
                    return(curTile);
                }

                foreach (Vector2Int direction in directions)
                {
                    Tile tile = FieldManager.GetTile(curTile.position + direction);
                    if (tile != null && !visited.Contains(tile))
                    {
                        frontier.Add(tile);
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// 유닛의 이동경로를 찾는 알고리즘.
        /// </summary>
        /// <param name="unit">이동 유닛</param>
        /// <param name="from">출발 위치</param>
        /// <param name="to">도착 위치</param>
        /// <returns></returns>
        public static List <Vector2Int> PathFindAlgorithm(Model.Unit agent, Vector2Int from, Vector2Int to)
        {
            if (FieldManager.GetTile(to) == null || FieldManager.GetTile(to).HasUnit())
            {
                Debug.LogWarning("길찾기 알고리즘 오류");
                return(null);
            }

            Node        node     = new Node(from, to);
            List <Node> frontier = new List <Node>(); // priority queue ordered by Path-Cost, with node as the only element
            List <Node> explored = new List <Node>(); // an empty set

            frontier.Add(node);

            while (true)
            {
                InfiniteLoopDebug.Run("Pathfind", "GetClosestReachableDest", 258);
                if (frontier.Count == 0)
                {
                    Debug.Log("목적지에 갈수 있는 길이 존재하지 않습니다.");
                    return(null); // 답이 없음.
                }

                node = Node.PopSmallestCostNode(frontier);
                frontier.Remove(node);

                if (node.unitPosition.Equals(to)) // goal test
                {
                    return(Node.RebuildPath(node));
                }

                explored.Add(node); // add node.State to explored

                foreach (var child in Node.GetAvilableNeighbor(agent, node))
                {
                    bool isExplored = false;
                    foreach (var item in explored)
                    {
                        if (item.unitPosition == child.unitPosition)
                        {
                            isExplored = true;
                        }
                    }
                    if (isExplored.Equals(true))
                    {
                        continue;
                    }

                    bool isFrontiered = false;

                    for (int i = frontier.Count - 1; i >= 0; i--)
                    {
                        if (frontier[i].unitPosition.Equals(child.unitPosition))
                        {
                            isFrontiered = true;
                            if (child.unitPosition == frontier[i].unitPosition &&
                                child.evaluationCost < frontier[i].evaluationCost)
                            {
                                frontier.Remove(frontier[i]);
                                frontier.Add(child);
                            }
                        }
                    }

                    if (isFrontiered.Equals(false))
                    {
                        frontier.Add(child);
                    }
                }
            }
        }