IEnumerator FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Stopwatch sw = new Stopwatch();

        sw.Start();

        Vector3[] waypoints   = new Vector3[0];
        bool      pathSuccess = false;

        Node startNode  = grid.NodeFromWorldPoint(startPos);
        Node targetNode = grid.NodeFromWorldPoint(targetPos);

        Heap <Node>    openSet   = new Heap <Node>(grid.MaxSize);
        HashSet <Node> closedSet = new HashSet <Node>();

        openSet.Add(startNode);

        if (startNode.walkable && targetNode.walkable)
        {
            while (openSet.Count > 0) //only breaks if target node is unreacheble
            {
                Node currentNode = openSet.RemoveFirst();
                closedSet.Add(currentNode);

                if (currentNode == targetNode) //if goal is reached
                {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in grid.GetNeighbours(currentNode)) //if open neighbour to current gets a lower gcost from using currents path(patrents), current is the neighbours parent, basically starts here
                {
                    if (!neighbour.walkable || closedSet.Contains(neighbour))
                    {
                        continue;
                    }

                    int movenCostToNeighbour = currentNode.gCost + getDistance(currentNode, neighbour);
                    if (movenCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                    {
                        neighbour.gCost  = movenCostToNeighbour;
                        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);
        }
        requsetManager.FinishedProcessingPath(waypoints, pathSuccess);
    }
Ejemplo n.º 2
0
    public void FindPath(PathRequest request, Action <PathResult> callback)
    {
        Stopwatch sw = new Stopwatch(); //check how long the method takes

        sw.Start();

        Vector3[] waypoints   = new Vector3[0];                       //contains the path
        bool      pathSuccess = false;                                //if path could be found

        Node startNode  = grid.NodeFromWorldPoint(request.pathStart); //get start and end in node
        Node targetNode = grid.NodeFromWorldPoint(request.pathEnd);

        Heap <Node>    openSet   = new Heap <Node>(grid.MaxSize); //create heap for all nodes that can be moved to
        HashSet <Node> closedSet = new HashSet <Node>();          //hash set for all nodes that can't be moved to

        openSet.Add(startNode);                                   //add the startnode for a starting point

        if (startNode.walkable && targetNode.walkable)
        {
            while (openSet.Count > 0)                     //only breaks if target node is unreacheble
            {
                Node currentNode = openSet.RemoveFirst(); //set current node to the first one in openSet and remove it from the openset
                closedSet.Add(currentNode);               //so you can't move to current node again

                if (currentNode == targetNode)            //if goal is reached
                {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (Node neighbour in grid.GetNeighbours(currentNode))   //if an open neighbour to the current node gets a lower gcost from using currents path (patrents), current is the neighbours parent
                {
                    if (!neighbour.walkable || closedSet.Contains(neighbour)) //if neighbour is not walkable or on the closed set skip it
                    {
                        continue;
                    }

                    int movenCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) + neighbour.movementPenalty; //the cost for moving to the neighbour
                    if (movenCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))                                     //if the new cost is lower than the old or neighbour has not yet been added to openset
                    {
                        neighbour.gCost  = movenCostToNeighbour;                                                                    //set g cost
                        neighbour.hCost  = GetDistance(neighbour, targetNode);                                                      //set h cost
                        neighbour.parent = currentNode;                                                                             //set parent to backtrack to start from goal

                        if (!openSet.Contains(neighbour))                                                                           //if node was not in openset, add it
                        {
                            openSet.Add(neighbour);
                        }
                        else
                        {
                            openSet.UpdateItem(neighbour); //else, just update heap
                        }
                    }
                }
            }
        }
        if (pathSuccess)
        {
            waypoints   = RetracePath(startNode, targetNode); //if path was found, save it in the array
            pathSuccess = waypoints.Length > 0;
        }
        callback(new PathResult(waypoints, pathSuccess, request.callback)); //tell request manager that the path is found
        //UnityEngine.Debug.Log(GC.GetTotalMemory(true) + " Bytes");
    }