/** Sets up all needed variables and scans the graphs.
	 * Calls Initialize, starts the ReturnPaths coroutine and scans all graphs.
	 * Also starts threads if using multithreading
	 * \see #OnAwakeSettings */
	public void Awake () {
		//Very important to set this. Ensures the singleton pattern holds
		active = this;
		
		if (FindObjectsOfType (typeof(AstarPath)).Length > 1) {
			Debug.LogError ("You should NOT have more than one AstarPath component in the scene at any time.\n" +
				"This can cause serious errors since the AstarPath component builds around a singleton pattern.");
		}
		
		//Disable GUILayout to gain some performance, it is not used in the OnGUI call
		useGUILayout = false;
		
		isEditor = Application.isEditor;
		
		if (OnAwakeSettings != null) {
			OnAwakeSettings ();
		}
		
		//To make sure all graph modifiers have been enabled before scan (to avoid script run order issues)
		GraphModifier.FindAllModifiers ();
		RelevantGraphSurface.FindAllGraphSurfaces ();
		
		int numThreads = CalculateThreadCount (threadCount);
		
		
		threads = new Thread[numThreads];
		//Thread info, will contain at least one item since the coroutine "thread" is thought of as a real thread in this case
		threadInfos = new PathThreadInfo[System.Math.Max(numThreads,1)];
		
		//Set up path queue with the specified number of receivers
		pathQueue = new ThreadControlQueue(threadInfos.Length);
		
		for (int i=0;i<threadInfos.Length;i++) {
			threadInfos[i] = new PathThreadInfo(i,this,new PathHandler());
		}
		for (int i=0;i<threads.Length;i++) {
			threads[i] = new Thread (new ParameterizedThreadStart (CalculatePathsThreaded));
			threads[i].Name = "Pathfinding Thread " + i;
			threads[i].IsBackground = true;
		}
		
		
		//Start coroutine if not using multithreading
		if (numThreads == 0) {
			threadEnumerator = CalculatePaths (threadInfos[0]);
		} else {
			threadEnumerator = null;
		}
		
		//Start pathfinding threads
		for (int i=0;i<threads.Length;i++) {
			if (logPathResults == PathLog.Heavy)
				Debug.Log ("Starting pathfinding thread "+i);
			threads[i].Start (threadInfos[i]);
		}

		Thread graphUpdateThread = new Thread (new ParameterizedThreadStart(ProcessGraphUpdatesAsync));
		graphUpdateThread.IsBackground = true;
		graphUpdateThread.Start (this);
		
		Initialize ();
		
#if !PhotonImplementation
		
		// Flush work items, possibly added in initialize to load graph data
		FlushWorkItems();
		
		if (scanOnStartup) {
			if (!astarData.cacheStartup || astarData.data_cachedStartup == null) {
				Scan ();
			}
		}
		
#endif	
	}
	/** Replacement for UnityEngine's StartCoroutine */
	public void StartCoroutine (IEnumerator update) {
		if (activeThread != null && activeThread.IsAlive) {
			Debug.Log ("Can only start one coroutine at a time, please end the current running thread first (activeThread)");
			return;
		}
		
		//Execute to the first yield
		if (!update.MoveNext ()) {
			return;
		}
		
		activeThread = new Thread (StartCoroutineInternal);
		activeThread.Start (update);
	}
Exemple #3
0
    /// <param name="path">The path to wait for. The path must be started, otherwise an exception will be thrown.</param>
    public static void BlockUntilCalculated(Path path)
    {
        if (active == null)
        {
            throw new System.Exception("Pathfinding is not correctly initialized in this scene (yet?). " +
                                       "AstarPath.active is null.\nDo not call this function in Awake");
        }

        if (path == null)
        {
            throw new System.ArgumentNullException("Path must not be null");
        }

        if (active.pathProcessor.queue.IsTerminating)
        {
            return;
        }

        if (path.PipelineState == PathState.Created)
        {
            throw new System.Exception("The specified path has not been started yet.");
        }

        waitForPathDepth++;

        if (waitForPathDepth == 5)
        {
            Debug.LogError("You are calling the BlockUntilCalculated function recursively (maybe from a path callback). Please don't do this.");
        }

        if (path.PipelineState < PathState.ReturnQueue)
        {
            if (active.IsUsingMultithreading)
            {
                while (path.PipelineState < PathState.ReturnQueue)
                {
                    if (active.pathProcessor.queue.IsTerminating)
                    {
                        waitForPathDepth--;
                        throw new System.Exception("Pathfinding Threads seem to have crashed.");
                    }

                    // Wait for threads to calculate paths
                    Thread.Sleep(1);
                    active.PerformBlockingActions(true);
                }
            }
            else
            {
                while (path.PipelineState < PathState.ReturnQueue)
                {
                    if (active.pathProcessor.queue.IsEmpty && path.PipelineState != PathState.Processing)
                    {
                        waitForPathDepth--;
                        throw new System.Exception("Critical error. Path Queue is empty but the path state is '" + path.PipelineState + "'");
                    }

                    // Calculate some paths
                    active.pathProcessor.TickNonMultithreaded();
                    active.PerformBlockingActions(true);
                }
            }
        }

        active.pathReturnQueue.ReturnPaths(false);
        waitForPathDepth--;
    }