StartFastProfile() private method

private StartFastProfile ( int tag ) : void
tag int
return void
Ejemplo n.º 1
0
        /** Opens nodes until there are none left to search (or until the max time limit has been exceeded) */
        public override void CalculateStep(long targetTick)
        {
            int counter = 0;

            //Continue to search while there hasn't ocurred an error and the end hasn't been found
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                AstarProfiler.StartFastProfile(4);
                //Debug.DrawRay ((Vector3)currentR.node.Position, Vector3.up*2,Color.red);

                //Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                // Insert into internal search tree
                if (saveParents)
                {
                    parents[currentR.node] = currentR.parent.node;
                }

                AstarProfiler.EndFastProfile(4);

                //any nodes left to search?
                if (pathHandler.HeapEmpty())
                {
                    CompleteState = PathCompleteState.Complete;
                    break;
                }

                //Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.PopNode();
                AstarProfiler.EndFastProfile(7);

                //Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    //Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (DateTime.UtcNow.Ticks >= targetTick)
                    {
                        //Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }
                    counter = 0;

                    if (searchedNodes > 1000000)
                    {
                        throw new Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }
        }
		protected override void CalculateStep (long targetTick) {
			int counter = 0;

			// Continue to search as long as we haven't encountered an error and we haven't found the target
			while (CompleteState == PathCompleteState.NotCalculated) {
				// @Performance Just for debug info
				searchedNodes++;

				// The node might be the target node for one of the paths
				if (currentR.flag1) {
					// Close the current node, if the current node is the target node then the path is finnished
					for (int i = 0; i < targetNodes.Length; i++) {
						if (!targetsFound[i] && currentR.node == targetNodes[i]) {
							FoundTarget(currentR, i);
							if (CompleteState != PathCompleteState.NotCalculated) {
								break;
							}
						}
					}

					if (targetNodeCount <= 0) {
						CompleteState = PathCompleteState.Complete;
						break;
					}
				}

				// Loop through all walkable neighbours of the node and add them to the open list.
				currentR.node.Open(this, currentR, pathHandler);

				// Any nodes left to search?
				if (pathHandler.heap.isEmpty) {
					CompleteState = PathCompleteState.Complete;
					break;
				}

				// Select the node with the lowest F score and remove it from the open list
				AstarProfiler.StartFastProfile(7);
				currentR = pathHandler.heap.Remove();
				AstarProfiler.EndFastProfile(7);

				// Check for time every 500 nodes, roughly every 0.5 ms usually
				if (counter > 500) {
					// Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
					if (System.DateTime.UtcNow.Ticks >= targetTick) {
						// Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
						return;
					}

					counter = 0;
				}

				counter++;
			}
		}
Ejemplo n.º 3
0
        protected override void CalculateStep(long targetTick)
        {
            int counter = 0;

            //Continue to search as long as we haven't encountered an error and we haven't found the target
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                //--- Here's the important stuff
                //Close the current node, if the current node satisfies the ending condition, the path is finished
                if (endingCondition.TargetFound(currentR))
                {
                    CompleteState = PathCompleteState.Complete;
                    break;
                }

                if (!currentR.flag1)
                {
                    //Add Node to allNodes
                    allNodes.Add(currentR.node);
                    currentR.flag1 = true;
                }

#if ASTARDEBUG
                Debug.DrawRay((Vector3)currentR.node.position, Vector3.up * 5, Color.cyan);
#endif

                //--- Here the important stuff ends

                AstarProfiler.StartFastProfile(4);
                //Debug.DrawRay ((Vector3)currentR.node.Position, Vector3.up*2,Color.red);

                //Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                AstarProfiler.EndFastProfile(4);

                //any nodes left to search?
                if (pathHandler.heap.isEmpty)
                {
                    CompleteState = PathCompleteState.Complete;
                    break;
                }


                //Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.heap.Remove();
                AstarProfiler.EndFastProfile(7);

                //Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    //Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (DateTime.UtcNow.Ticks >= targetTick)
                    {
                        //Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }
                    counter = 0;

                    if (searchedNodes > 1000000)
                    {
                        throw new Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }
        }
Ejemplo n.º 4
0
        /** Calculates the path until completed or until the time has passed \a targetTick.
         * Usually a check is only done every 500 nodes if the time has passed \a targetTick.
         * Time/Ticks are got from System.DateTime.UtcNow.Ticks.
         *
         * Basic outline of what the function does for the standard path (Pathfinding.ABPath).
         * \code
         * while the end has not been found and no error has ocurred
         * check if we have reached the end
         * if so, exit and return the path
         *
         * open the current node, i.e loop through its neighbours, mark them as visited and put them on a heap
         *
         * check if there are still nodes left to process (or have we searched the whole graph)
         * if there are none, flag error and exit
         *
         * pop the next node of the heap and set it as current
         *
         * check if the function has exceeded the time limit
         * if so, return and wait for the function to get called again
         * \endcode
         */
        public override void CalculateStep(long targetTick)
        {
            int counter = 0;

            // Continue to search while there hasn't ocurred an error and the end hasn't been found
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                // Close the current node, if the current node is the target node then the path is finished
                if (currentR.flag1)
                {
                    // We found a target point
                    // Mark that node as the end point
                    CompleteWith(currentR.node);
                    break;
                }

                if (currentR.H < partialBestTarget.H)
                {
                    partialBestTarget = currentR;
                }

                AstarProfiler.StartFastProfile(4);

                // Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                AstarProfiler.EndFastProfile(4);

                // Any nodes left to search?
                if (pathHandler.heap.isEmpty)
                {
                    Error();
                    LogError("Searched whole area but could not find target");
                    return;
                }

                // Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.heap.Remove();
                AstarProfiler.EndFastProfile(7);

                // Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    // Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (System.DateTime.UtcNow.Ticks >= targetTick)
                    {
                        // Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }
                    counter = 0;

                    // Mostly for development
                    if (searchedNodes > 1000000)
                    {
                        throw new System.Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }

            AstarProfiler.StartProfile("Trace");

            if (CompleteState == PathCompleteState.Complete)
            {
                Trace(currentR);
            }
            else if (calculatePartial && partialBestTarget != null)
            {
                CompleteState = PathCompleteState.Partial;
                Trace(partialBestTarget);
            }

            AstarProfiler.EndProfile();
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Main pathfinding method.
        /// This method will calculate the paths in the pathfinding queue.
        ///
        /// See: CalculatePathsThreaded
        /// See: StartPath
        /// </summary>
        IEnumerator CalculatePaths(PathHandler pathHandler)
        {
            // Max number of ticks before yielding/sleeping
            long maxTicks   = (long)(astar.maxFrameTime * 10000);
            long targetTick = System.DateTime.UtcNow.Ticks + maxTicks;

            while (true)
            {
                // The path we are currently calculating
                Path p = null;

                AstarProfiler.StartProfile("Path Queue");

                // Try to get the next path to be calculated
                bool blockedBefore = false;
                while (p == null)
                {
                    try {
                        p              = queue.PopNoBlock(blockedBefore);
                        blockedBefore |= p == null;
                    } catch (ThreadControlQueue.QueueTerminationException) {
                        yield break;
                    }

                    if (p == null)
                    {
                        AstarProfiler.EndProfile();
                        yield return(null);

                        AstarProfiler.StartProfile("Path Queue");
                    }
                }

                AstarProfiler.EndProfile();

                AstarProfiler.StartProfile("Path Calc");

                IPathInternals ip = (IPathInternals)p;

                // Max number of ticks we are allowed to continue working in one run
                // One tick is 1/10000 of a millisecond
                maxTicks = (long)(astar.maxFrameTime * 10000);

                ip.PrepareBase(pathHandler);

                // Now processing the path
                // Will advance to Processing
                ip.AdvanceState(PathState.Processing);

                // Call some callbacks
                // It needs to be stored in a local variable to avoid race conditions
                var tmpOnPathPreSearch = OnPathPreSearch;
                if (tmpOnPathPreSearch != null)
                {
                    tmpOnPathPreSearch(p);
                }

                // Tick for when the path started, used for calculating how long time the calculation took
                long startTicks = System.DateTime.UtcNow.Ticks;
                long totalTicks = 0;

                AstarProfiler.StartFastProfile(8);

                AstarProfiler.StartFastProfile(0);
                //Prepare the path
                AstarProfiler.StartProfile("Path Prepare");
                ip.Prepare();
                AstarProfiler.EndProfile("Path Prepare");
                AstarProfiler.EndFastProfile(0);

                // Check if the Prepare call caused the path to complete
                // If this happens the path usually failed
                if (p.CompleteState == PathCompleteState.NotCalculated)
                {
                    // For debug uses, we set the last computed path to p, so we can view debug info on it in the editor (scene view).
                    astar.debugPathData = ip.PathHandler;
                    astar.debugPathID   = p.pathID;

                    // Initialize the path, now ready to begin search
                    AstarProfiler.StartProfile("Path Initialize");
                    ip.Initialize();
                    AstarProfiler.EndProfile();

                    // The error can turn up in the Init function
                    while (p.CompleteState == PathCompleteState.NotCalculated)
                    {
                        // Do some work on the path calculation.
                        // The function will return when it has taken too much time
                        // or when it has finished calculation
                        AstarProfiler.StartFastProfile(2);

                        AstarProfiler.StartProfile("Path Calc Step");
                        ip.CalculateStep(targetTick);
                        AstarProfiler.EndFastProfile(2);

                        AstarProfiler.EndProfile();

                        // If the path has finished calculation, we can break here directly instead of sleeping
                        // Improves latency
                        if (p.CompleteState != PathCompleteState.NotCalculated)
                        {
                            break;
                        }

                        AstarProfiler.EndFastProfile(8);
                        totalTicks += System.DateTime.UtcNow.Ticks - startTicks;
                        // Yield/sleep so other threads can work

                        AstarProfiler.EndProfile();
                        yield return(null);

                        AstarProfiler.StartProfile("Path Calc");

                        startTicks = System.DateTime.UtcNow.Ticks;
                        AstarProfiler.StartFastProfile(8);

                        // Cancel function (and thus the thread) if no more paths should be accepted.
                        // This is done when the A* object is about to be destroyed
                        // The path is returned and then this function will be terminated (see similar IF statement higher up in the function)
                        if (queue.IsTerminating)
                        {
                            p.FailWithError("AstarPath object destroyed");
                        }

                        targetTick = System.DateTime.UtcNow.Ticks + maxTicks;
                    }

                    totalTicks += System.DateTime.UtcNow.Ticks - startTicks;
                    p.duration  = totalTicks * 0.0001F;

#if ProfileAstar
                    System.Threading.Interlocked.Increment(ref AstarPath.PathsCompleted);
#endif
                }

                // Cleans up node tagging and other things
                ip.Cleanup();

                AstarProfiler.EndFastProfile(8);

                // Call the immediate callback
                // It needs to be stored in a local variable to avoid race conditions
                var tmpImmediateCallback = p.immediateCallback;
                if (tmpImmediateCallback != null)
                {
                    tmpImmediateCallback(p);
                }

                AstarProfiler.StartFastProfile(13);

                // It needs to be stored in a local variable to avoid race conditions
                var tmpOnPathPostSearch = OnPathPostSearch;
                if (tmpOnPathPostSearch != null)
                {
                    tmpOnPathPostSearch(p);
                }

                AstarProfiler.EndFastProfile(13);

                // Push the path onto the return stack
                // It will be detected by the main Unity thread and returned as fast as possible (the next late update)
                returnQueue.Enqueue(p);

                ip.AdvanceState(PathState.ReturnQueue);

                AstarProfiler.EndProfile();

                // Wait a bit if we have calculated a lot of paths
                if (System.DateTime.UtcNow.Ticks > targetTick)
                {
                    yield return(null);

                    targetTick = System.DateTime.UtcNow.Ticks + maxTicks;
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Main pathfinding method (multithreaded).
        /// This method will calculate the paths in the pathfinding queue when multithreading is enabled.
        ///
        /// See: CalculatePaths
        /// See: StartPath
        /// </summary>
        void CalculatePathsThreaded(PathHandler pathHandler)
        {
#if UNITY_2017_3_OR_NEWER
            UnityEngine.Profiling.Profiler.BeginThreadProfiling("Pathfinding", "Pathfinding thread #" + (pathHandler.threadID + 1));
#endif

#if !ASTAR_FAST_BUT_NO_EXCEPTIONS
            try {
#endif

            // Max number of ticks we are allowed to continue working in one run.
            // One tick is 1/10000 of a millisecond.
            // We need to check once in a while if the thread should be stopped.
            long maxTicks   = (long)(10 * 10000);
            long targetTick = System.DateTime.UtcNow.Ticks + maxTicks;
            while (true)
            {
                // The path we are currently calculating
                Path path = queue.Pop();
#if UNITY_2017_3_OR_NEWER
                profilingSampler.Begin();
#endif
                // Access the internal implementation methods
                IPathInternals ipath = (IPathInternals)path;


                AstarProfiler.StartFastProfile(0);
                ipath.PrepareBase(pathHandler);

                // Now processing the path
                // Will advance to Processing
                ipath.AdvanceState(PathState.Processing);

                // Call some callbacks
                if (OnPathPreSearch != null)
                {
                    OnPathPreSearch(path);
                }

                // Tick for when the path started, used for calculating how long time the calculation took
                long startTicks = System.DateTime.UtcNow.Ticks;

                // Prepare the path
                ipath.Prepare();

                AstarProfiler.EndFastProfile(0);

                if (path.CompleteState == PathCompleteState.NotCalculated)
                {
                    // For visualization purposes, we set the last computed path to p, so we can view debug info on it in the editor (scene view).
                    astar.debugPathData = ipath.PathHandler;
                    astar.debugPathID   = path.pathID;

                    AstarProfiler.StartFastProfile(1);

                    // Initialize the path, now ready to begin search
                    ipath.Initialize();

                    AstarProfiler.EndFastProfile(1);

                    // Loop while the path has not been fully calculated
                    while (path.CompleteState == PathCompleteState.NotCalculated)
                    {
                        // Do some work on the path calculation.
                        // The function will return when it has taken too much time
                        // or when it has finished calculation
                        AstarProfiler.StartFastProfile(2);
                        ipath.CalculateStep(targetTick);
                        AstarProfiler.EndFastProfile(2);

                        targetTick = System.DateTime.UtcNow.Ticks + maxTicks;

                        // Cancel function (and thus the thread) if no more paths should be accepted.
                        // This is done when the A* object is about to be destroyed
                        // The path is returned and then this function will be terminated
                        if (queue.IsTerminating)
                        {
                            path.FailWithError("AstarPath object destroyed");
                        }
                    }

                    path.duration = (System.DateTime.UtcNow.Ticks - startTicks) * 0.0001F;

#if ProfileAstar
                    System.Threading.Interlocked.Increment(ref AstarPath.PathsCompleted);
                    System.Threading.Interlocked.Add(ref AstarPath.TotalSearchTime, System.DateTime.UtcNow.Ticks - startTicks);
#endif
                }

                // Cleans up node tagging and other things
                ipath.Cleanup();

                AstarProfiler.StartFastProfile(9);

                if (path.immediateCallback != null)
                {
                    path.immediateCallback(path);
                }

                if (OnPathPostSearch != null)
                {
                    OnPathPostSearch(path);
                }

                // Push the path onto the return stack
                // It will be detected by the main Unity thread and returned as fast as possible (the next late update hopefully)
                returnQueue.Enqueue(path);

                // Will advance to ReturnQueue
                ipath.AdvanceState(PathState.ReturnQueue);

                AstarProfiler.EndFastProfile(9);
#if UNITY_2017_3_OR_NEWER
                profilingSampler.End();
#endif
            }
#if !ASTAR_FAST_BUT_NO_EXCEPTIONS
        }

        catch (System.Exception e) {
#if !NETFX_CORE
            if (e is ThreadAbortException || e is ThreadControlQueue.QueueTerminationException)
#else
            if (e is ThreadControlQueue.QueueTerminationException)
#endif
            {
                if (astar.logPathResults == PathLog.Heavy)
                {
                    Debug.LogWarning("Shutting down pathfinding thread #" + pathHandler.threadID);
                }
                return;
            }
            Debug.LogException(e);
            Debug.LogError("Unhandled exception during pathfinding. Terminating.");
            // Unhandled exception, kill pathfinding
            queue.TerminateReceivers();
        } finally {
#if UNITY_2017_3_OR_NEWER
            UnityEngine.Profiling.Profiler.EndThreadProfiling();
#endif
        }
#endif

            Debug.LogError("Error : This part should never be reached.");
            queue.ReceiverTerminated();
        }
Ejemplo n.º 7
0
        /** Main pathfinding method (multithreaded).
         * This method will calculate the paths in the pathfinding queue when multithreading is enabled.
         *
         * \see CalculatePaths
         * \see StartPath
         *
         * \astarpro
         */
        void CalculatePathsThreaded(PathThreadInfo threadInfo)
        {
#if !ASTAR_FAST_BUT_NO_EXCEPTIONS
            try {
#endif

            //Initialize memory for this thread
            PathHandler runData = threadInfo.runData;

            if (runData.nodes == null)
            {
                throw new System.NullReferenceException("NodeRuns must be assigned to the threadInfo.runData.nodes field before threads are started\nthreadInfo is an argument to the thread functions");
            }

            //Max number of ticks before yielding/sleeping
            long maxTicks   = (long)(astar.maxFrameTime * 10000);
            long targetTick = System.DateTime.UtcNow.Ticks + maxTicks;

            while (true)
            {
                //The path we are currently calculating
                Path p = queue.Pop();

                //Max number of ticks we are allowed to continue working in one run
                //One tick is 1/10000 of a millisecond
                maxTicks = (long)(astar.maxFrameTime * 10000);


                AstarProfiler.StartFastProfile(0);
                p.PrepareBase(runData);

                //Now processing the path
                //Will advance to Processing
                p.AdvanceState(PathState.Processing);

                //Call some callbacks
                if (OnPathPreSearch != null)
                {
                    OnPathPreSearch(p);
                }

                //Tick for when the path started, used for calculating how long time the calculation took
                long startTicks = System.DateTime.UtcNow.Ticks;
                long totalTicks = 0;

                //Prepare the path
                p.Prepare();

                AstarProfiler.EndFastProfile(0);

                if (!p.IsDone())
                {
                    //For debug uses, we set the last computed path to p, so we can view debug info on it in the editor (scene view).
                    astar.debugPath = p;

                    AstarProfiler.StartFastProfile(1);

                    //Initialize the path, now ready to begin search
                    p.Initialize();

                    AstarProfiler.EndFastProfile(1);

                    //The error can turn up in the Init function
                    while (!p.IsDone())
                    {
                        //Do some work on the path calculation.
                        //The function will return when it has taken too much time
                        //or when it has finished calculation
                        AstarProfiler.StartFastProfile(2);
                        p.CalculateStep(targetTick);
                        p.searchIterations++;

                        AstarProfiler.EndFastProfile(2);

                        // If the path has finished calculation, we can break here directly instead of sleeping
                        if (p.IsDone())
                        {
                            break;
                        }

                        // Yield/sleep so other threads can work
                        totalTicks += System.DateTime.UtcNow.Ticks - startTicks;
                        Thread.Sleep(0);
                        startTicks = System.DateTime.UtcNow.Ticks;

                        targetTick = startTicks + maxTicks;

                        // Cancel function (and thus the thread) if no more paths should be accepted.
                        // This is done when the A* object is about to be destroyed
                        // The path is returned and then this function will be terminated
                        if (queue.IsTerminating)
                        {
                            p.Error();
                        }
                    }

                    totalTicks += System.DateTime.UtcNow.Ticks - startTicks;
                    p.duration  = totalTicks * 0.0001F;

#if ProfileAstar
                    System.Threading.Interlocked.Increment(ref AstarPath.PathsCompleted);
                    System.Threading.Interlocked.Add(ref AstarPath.TotalSearchedNodes, p.searchedNodes);
                    System.Threading.Interlocked.Add(ref AstarPath.TotalSearchTime, totalTicks);
#endif
                }

                // Cleans up node tagging and other things
                p.Cleanup();

                AstarProfiler.StartFastProfile(9);

                if (p.immediateCallback != null)
                {
                    p.immediateCallback(p);
                }

                if (OnPathPostSearch != null)
                {
                    OnPathPostSearch(p);
                }

                // Push the path onto the return stack
                // It will be detected by the main Unity thread and returned as fast as possible (the next late update hopefully)
                returnQueue.Enqueue(p);

                // Will advance to ReturnQueue
                p.AdvanceState(PathState.ReturnQueue);

                AstarProfiler.EndFastProfile(9);

                // Wait a bit if we have calculated a lot of paths
                if (System.DateTime.UtcNow.Ticks > targetTick)
                {
                    Thread.Sleep(1);
                    targetTick = System.DateTime.UtcNow.Ticks + maxTicks;
                }
            }
#if !ASTAR_FAST_BUT_NO_EXCEPTIONS
        }

        catch (System.Exception e) {
#if !NETFX_CORE
            if (e is ThreadAbortException || e is ThreadControlQueue.QueueTerminationException)
#else
            if (e is ThreadControlQueue.QueueTerminationException)
#endif
            {
                if (astar.logPathResults == PathLog.Heavy)
                {
                    Debug.LogWarning("Shutting down pathfinding thread #" + threadInfo.threadIndex);
                }
                return;
            }
            Debug.LogException(e);
            Debug.LogError("Unhandled exception during pathfinding. Terminating.");
            //Unhandled exception, kill pathfinding
            queue.TerminateReceivers();
        }
#endif

            Debug.LogError("Error : This part should never be reached.");
            queue.ReceiverTerminated();
        }
Ejemplo n.º 8
0
        public override void CalculateStep(long targetTick)
        {
            int counter = 0;

            //Continue to search while there hasn't ocurred an error and the end hasn't been found
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                //Close the current node, if the current node is the target node then the path is finnished
                if (currentR.G >= searchLength)
                {
                    nodesEvaluatedRep++;

                    if (chosenNodeR == null)
                    {
                        chosenNodeR = currentR;
                    }
                    else if (rnd.NextDouble() <= 1.0f / nodesEvaluatedRep)
                    {
                        chosenNodeR = currentR;
                    }

                    if (currentR.G >= searchLength + spread)
                    {
                        CompleteState = PathCompleteState.Complete;
                        break;
                    }
                }
                else if (currentR.G > maxGScore)
                {
                    maxGScore      = (int)currentR.G;
                    maxGScoreNodeR = currentR;
                }

                AstarProfiler.StartFastProfile(4);
                //Debug.DrawRay ((Vector3)currentR.node.Position, Vector3.up*2,Color.red);

                //Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                AstarProfiler.EndFastProfile(4);

                //any nodes left to search?
                if (pathHandler.HeapEmpty())
                {
                    if (chosenNodeR != null)
                    {
                        CompleteState = PathCompleteState.Complete;
                    }
                    else if (maxGScoreNodeR != null)
                    {
                        chosenNodeR   = maxGScoreNodeR;
                        CompleteState = PathCompleteState.Complete;
                    }
                    else
                    {
                        LogError("Not a single node found to search");
                        Error();
                    }
                    break;
                }


                //Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.PopNode();
                AstarProfiler.EndFastProfile(7);

                //Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    //Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (System.DateTime.UtcNow.Ticks >= targetTick)
                    {
                        //Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }
                    counter = 0;

                    if (searchedNodes > 1000000)
                    {
                        throw new System.Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }


            AstarProfiler.StartProfile("Trace");

            if (CompleteState == PathCompleteState.Complete)
            {
                Trace(chosenNodeR);
            }

            AstarProfiler.EndProfile();
        }