/// <summary>
    /// Internal function that implements the path-finding algorithm.
    /// </summary>
    /// <param name="grid">Grid to search.</param>
    /// <param name="startPos">Starting position.</param>
    /// <param name="targetPos">Ending position.</param>
    /// <param name="distance">The type of distance, Euclidean or Manhattan.</param>
    /// <param name="ignorePrices">If true, will ignore tile price (how much it "cost" to walk on).</param>
    /// <returns>List of grid nodes that represent the path to walk.</returns>
    private static List <Node> _ImpFindPath(PathfindGrid grid, Point startPos, Point targetPos, DistanceType distance = DistanceType.Euclidean, bool ignorePrices = false)
    {
        Node startNode  = grid.nodes[startPos.x, startPos.y];
        Node targetNode = grid.nodes[targetPos.x, targetPos.y];

        List <Node>    openSet   = new List <Node>();
        HashSet <Node> closedSet = new HashSet <Node>();

        openSet.Add(startNode);

        while (openSet.Count > 0)
        {
            Node currentNode = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
                {
                    currentNode = openSet[i];
                }
            }

            openSet.Remove(currentNode);
            closedSet.Add(currentNode);

            if (currentNode == targetNode)
            {
                return(RetracePath(grid, startNode, targetNode));
            }

            foreach (Node neighbour in grid.GetNeighbours(currentNode, distance))
            {
                if (!neighbour.walkable || closedSet.Contains(neighbour))
                {
                    continue;
                }

                int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) * (ignorePrices ? 1 : (int)(10.0f * neighbour.price));
                if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                {
                    neighbour.gCost  = newMovementCostToNeighbour;
                    neighbour.hCost  = GetDistance(neighbour, targetNode);
                    neighbour.parent = currentNode;

                    if (!openSet.Contains(neighbour))
                    {
                        openSet.Add(neighbour);
                    }
                }
            }
        }

        return(null);
    }
Example #2
0
    IEnumerator FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Vector3[] waypoints   = new Vector3[0];
        bool      pathSuccess = false;

        Node startNode  = _grid.NodeFromWorldInput(startPos);
        Node targetNode = _grid.NodeFromWorldInput(targetPos);

        if (startNode.Walkable && targetNode.Walkable)
        {
            Heap <Node>    openSet   = new Heap <Node>(_grid.MaxSize);
            HashSet <Node> closedSet = new HashSet <Node>();
            openSet.Add(startNode);

            while (openSet.Count > 0)
            {
                Node currentNode = openSet.RemoveFirst();

                closedSet.Add(currentNode);

                if (currentNode == targetNode)
                {
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in _grid.GetNeighbours(currentNode))
                {
                    if (!neighbour.Walkable || closedSet.Contains(neighbour))
                    {
                        continue;
                    }

                    int newMoveCostToNeighbour = currentNode.GCost + GetDistance(currentNode, neighbour);
                    if (newMoveCostToNeighbour < neighbour.GCost ||
                        !openSet.Contains(neighbour))
                    {
                        neighbour.GCost  = newMoveCostToNeighbour;
                        neighbour.HCost  = GetDistance(neighbour, targetNode);
                        neighbour.Parent = currentNode;

                        if (!openSet.Contains(neighbour))
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour);
                        }
                    }
                }
            }
        }

        yield return(null);

        if (pathSuccess)
        {
            waypoints = RetracePath(startNode, targetNode);
        }

        _requestManager.FinishedProcessingPath(waypoints, pathSuccess);
    }