context: //Define optimizations is a A* Pathfinding Project Pro only feature
  //#define ProfileAstar	//Enables profiling of the pathfinding process
  //#define ASTARDEBUG			//Enables more debugging messages, enable if this script is behaving weird (crashing or throwing NullReference exceptions or something)
  //#define NoGUI			//Disables the use of the OnGUI function, can eventually improve performance by a tiny bit (disables the InGame option for path debugging)
  //#define ASTAR_SINGLE_THREAD_OPTIMIZE //Optimizes performance and memory for single and dual core computers/smartphones. Recommended if you only run pathfinding in on thread or in the unity thread. Reduces memory usage quite a lot.
  //#define ASTAR_MORE_PATH_IDS //Increases the number of pathIDs from 2^16 to 2^32. Uses more memory.
  //#define ASTAR_FAST_BUT_NO_EXCEPTIONS
  
  using UnityEngine;
  using System.Collections;
  using System.Collections.Generic;
  using System.Threading;
  using Pathfinding;
  
  [AddComponentMenu ("Pathfinding/Pathfinder")]
  /** Main Pathfinding System.
   * This class handles all the pathfinding system, calculates all paths and stores the info.\n
   * This class is a singleton class, meaning it should only exist at most one active instance of it in the scene.\n
   * It might be a bit hard to use directly, usually interfacing with the pathfinding system is done through the Seeker class.
   * 
   * \nosubgrouping
   * \ingroup relevant */
  public class AstarPath : MonoBehaviour {
      #region SINGLETON
      private static AstarPath _instance = null;
      public static AstarPath Instance { get { return _instance; } }
      #endregion
  	
  	/** The version number for the A* %Pathfinding Project
  	 */
  	public static System.Version Version {
  		get {
  			return new System.Version (3,2,5,1);
  		}
  	}
  	
  	public enum AstarDistribution { WebsiteDownload, AssetStore };
  	
  	/** Used by the editor to guide the user to the correct place to download updates */
  	public static readonly AstarDistribution Distribution = AstarDistribution.WebsiteDownload;
  	
  	/** Used by the editor to show some Pro specific stuff.
  	 * Note that setting this to true will not grant you any additional features */
  	public static readonly bool HasPro = false;
  	
  	/** See Pathfinding.AstarData */
  	public System.Type[] graphTypes {
  		get {
  			return astarData.graphTypes;
  		}
  	}
  	
  	/** Reference to the Pathfinding.AstarData object for this graph. The AstarData object stores information about all graphs. */
  	public AstarData astarData;
  	
  	/** Returns the active AstarPath object in the scene.*/
  	public new static AstarPath active;
  	
  	/** Shortcut to Pathfinding.AstarData.graphs */
  	public NavGraph[] graphs {
  		get {
  			if (astarData == null)
  				astarData = new AstarData ();
  			return astarData.graphs;
  		}
  		set {
  			if (astarData == null)
  				astarData = new AstarData ();
  			astarData.graphs = value;
  		}
  	}
  	
  #region InspectorDebug
  	/** @name Inspector - Debug
  	 * @{ */
  	
  	/** Toggle for showing the gizmo debugging for the graphs in the scene view (editor only). */
  	public bool showNavGraphs = true;
  	
  	/** Toggle to show unwalkable nodes.
  	  * \see unwalkableNodeDebugSize */
  	public bool showUnwalkableNodes = true;
  	
  	/** The mode to use for drawing nodes in the sceneview.
  	 * \see Pathfinding.GraphDebugMode
  	 */
  	public GraphDebugMode debugMode;
  	
  	/** Low value to use for certain #debugMode modes.
  	 * For example if #debugMode is set to G, this value will determine when the node will be totally red.
  	 * \see #debugRoof
  	 */
  	public float debugFloor = 0;
  	
  	/** High value to use for certain #debugMode modes.
  	 * For example if #debugMode is set to G, this value will determine when the node will be totally green.
  	 * \see #debugFloor
  	 */
  	public float debugRoof = 20000;
  	
  	/** If enabled, nodes will draw a line to their 'parent'.
  	 * This will show the search tree for the latest path. This is editor only.
  	 * \todo Add a showOnlyLastPath flag to indicate whether to draw every node or only the ones visited by the latest path.
  	 */
  	public bool	showSearchTree = false;
  	
  	/** Size of the red cubes shown in place of unwalkable nodes.
  	  * \see showUnwalkableNodes */
  	public float unwalkableNodeDebugSize = 0.3F;
  	
  	/** If enabled, only one node will be searched per search iteration (frame).
  	 * Used for debugging
  	 * \note Might not apply for all path types
  	 * \deprecated Probably does not work for ANY path types
  	 */
  	public bool stepByStep = true;
  	
  	/** The amount of debugging messages.
  	 * Use less debugging to improve performance (a bit) or just to get rid of the Console spamming.\n
  	 * Use more debugging (heavy) if you want more information about what the pathfinding is doing.\n
  	 * InGame will display the latest path log using in game GUI. */
  	public PathLog logPathResults = PathLog.Normal;
  	
  	/** @} */
  #endregion
  	
  #region InspectorSettings
  	/** @name Inspector - Settings
  	 * @{ */
  	
  	/** Max Nearest Node Distance.
  	 * When searching for a nearest node, this is the limit (world units) for how far away it is allowed to be.
  	 * \see Pathfinding.NNConstraint.constrainDistance
  	 */
  	public float maxNearestNodeDistance = 100;
  	
  	/** Max Nearest Node Distance Squared.
  	 * \see #maxNearestNodeDistance */
  	public float maxNearestNodeDistanceSqr {
  		get { return maxNearestNodeDistance*maxNearestNodeDistance; }
  	}
  	
  	/** If true, all graphs will be scanned in Awake.
  	 * This does not include loading from the cache.
  	 * If you disable this, you will have to call \link Scan AstarPath.active.Scan () \endlink yourself to enable pathfinding,
  	 * alternatively you could load a saved graph from a file.
  	 */
  	public bool scanOnStartup = true;
  	
  	/** Do a full GetNearest search for all graphs.
  	 * Additinal searches will normally only be done on the graph which in the first, fast searches proved to have the closest node.
  	 * With this setting on, additional searches will be done on all graphs.\n
  	 * More technically: GetNearestForce on all graphs will be called if true, otherwise only on the one graph which's GetNearest search returned the best node.\n
  	 * Usually faster when disabled, but higher quality searches when enabled.
  	 * When using a a navmesh or recast graph, for best quality, this setting should be combined with the Pathfinding.NavMeshGraph.accurateNearestNode setting set to true.
  	 * \note For the PointGraph this setting doesn't matter much as it has only one search mode.
  	 */
  	public bool fullGetNearestSearch = false;
  	
  	/** Prioritize graphs.
  	 * Graphs will be prioritized based on their order in the inspector.
  	 * The first graph which has a node closer than #prioritizeGraphsLimit will be chosen instead of searching all graphs.
  	 */
  	public bool prioritizeGraphs = false;
  	
  	/** Distance limit for #prioritizeGraphs.
  	 * \see #prioritizeGraphs
  	 */
  	public float prioritizeGraphsLimit = 1F;
  	
  	/** Reference to the color settings for this AstarPath object.
  	 * Color settings include for example which color the nodes should be in, in the sceneview. */
  	public AstarColor colorSettings;
  	
  	/** Stored tag names.
  	 * \see AstarPath.FindTagNames
  	 * \see AstarPath.GetTagNames
  	 */
  	[SerializeField]
  	protected string[] tagNames = null;
  	
  	/** The heuristic to use.
  	 * The heuristic, often referred to as 'H' is the estimated cost from a node to the target.
  	 * Different heuristics affect how the path picks which one to follow from multiple possible with the same length
  	 * \see Pathfinding.Heuristic
  	 */
  	public Heuristic heuristic = Heuristic.Euclidean;
  	
  	/** The scale of the heuristic. If a smaller value than 1 is used, the pathfinder will search more nodes (slower).
  	 * If 0 is used, the pathfinding will be equal to dijkstra's algorithm.
  	 * If a value larger than 1 is used the pathfinding will (usually) be faster because it expands fewer nodes, but the paths might not longer be optimal
  	 */
  	public float heuristicScale = 1F;
  
  	/** Number of pathfinding threads to use.
  	 * Multithreading puts pathfinding in another thread, this is great for performance on 2+ core computers since the framerate will barely be affected by the pathfinding at all.
  	 * But this can cause strange errors and pathfinding stopping to work if you are not carefull (that is, if you are modifying the pathfinding scripts). For basic usage (not modding the pathfinding core) it should be safe.\n
  	 * - None indicates that the pathfinding is run in the Unity thread as a coroutine
  	 * - Automatic will try to adjust the number of threads to the number of cores and memory on the computer.
  	 * 	Less than 512mb of memory or a single core computer will make it revert to using no multithreading
  	 * \see CalculateThreadCount
  	 * \astarpro
  	 */
  	public ThreadCount threadCount = ThreadCount.None;
  	
  	/** Max number of milliseconds to spend each frame for pathfinding.
  	 * At least 500 nodes will be searched each frame (if there are that many to search).
  	 * When using multithreading this value is quite irrelevant,
  	 * but do not set it too low since that could add upp to some overhead, 10ms will work good for multithreading */
  	public float maxFrameTime = 1F;
  	
  	/** The initial max size of the binary heap.
  	 * The binary heaps will be expanded if necessary.
  	 */
  	public const int InitialBinaryHeapSize = 512;
  	
  	/** Recycle paths to reduce memory allocations.
  	 * This will put paths in a pool to be reused over and over again.
  	 * If you use this, your scripts using tht paths should copy the vectorPath array and node array (if used) because when the path is recycled,
  	 * those arrays will be replaced.
  	 * I.e you should not get data from it using myPath.someVariable (except when you get the path callback) because 'someVariable' might be changed when the path is recycled.
  	 * \note This feature is currently disabled because it didn't lead to much better memory management, but could seriously screw up stuff if the user was not careful.
  	 */
  	public bool recyclePaths = false;
  	
  	/** Defines the minimum amount of nodes in an area.
  	 * If an area has less than this amount of nodes, the area will be flood filled again with the area ID 254,
  	 * it shouldn't affect pathfinding in any significant way.\n
  	 * If you want to be able to separate areas from one another for some reason (for example to do a fast check to see if a path is at all possible)
  	 * you should set this variable to 0.\n
  	  * Can be found in A* Inspector-->Settings-->Min Area Size
  	  */
  	public int minAreaSize = 10;
  	
  	/** Limit graph updates. If toggled, graph updates will be executed less often (specified by #maxGraphUpdateFreq).*/
  	public bool limitGraphUpdates = true;
  	
  	/** How often should graphs be updated. If #limitGraphUpdates is true, this defines the minimum amount of seconds between each graph update.*/
  	public float maxGraphUpdateFreq = 0.2F;
  	
  	/** @} */
  #endregion
  	
  #region DebugVariables
  	/** @name Debug Members
  	 * @{ */
  	
  	/** How many paths has been computed this run. From application start.\n
  	 * Debugging variable */
  	public static int PathsCompleted = 0;
  	
  	public static System.Int64 				TotalSearchedNodes = 0;
  	public static System.Int64			 	TotalSearchTime = 0;
  	
  	/** The time it took for the last call to Scan() to complete.
  	 * Used to prevent automatically rescanning the graphs too often (editor only) */
  	public float lastScanTime = 0F;
  	
  	/** The path to debug using gizmos.
  	 * This is equal to the last path which was calculated,
  	 * it is used in the editor to draw debug information using gizmos.*/
  	public Path debugPath;
  	
  	/** NodeRunData from #debugPath.
  	 * Returns null if #debugPath is null
  	 */
  	public NodeRunData debugPathData {
  		get {
  			if (debugPath == null) return null;
  			return debugPath.runData;
  		}
  	}
  	
  	/** This is the debug string from the last completed path.
  	 * Will be updated if #logPathResults == PathLog.InGame */
  	public string inGameDebugPath;
  	
  	/* @} */
  #endregion
  	
  #region StatusVariables
  	
  	/** Set when scanning is being done. It will be true up until the FloodFill is done.
  	 * Used to better support Graph Update Objects called for example in OnPostScan */
  	public bool isScanning = false;
  	
  	/** Disables or enables new paths to be added to the queue.
  	  * Setting this to false also makes the pathfinding thread (if using multithreading) to abort as soon as possible.
  	  * It is used when OnDestroy is called to abort the pathfinding thread. */
  	private bool acceptNewPaths = true;
  	
  	/** Number of threads currently working.
  	  * Threads are sleeping when there is no work to be done or there is a work block (such as when updating graphs) */
  	private static int numActiveThreads = 0;
  	
  	/** Number of threads currently active.
  	 * This includes the pathfinding coroutine used for non-multithreading mode.
  	  */
  	public static int ActiveThreadsCount {
  		get { return numActiveThreads; }
  	}
  	
  	/** Number of parallel pathfinders.
  	 * Returns the number of concurrent processes which can calculate paths at once.
  	 * When using multithreading, this will be the number of threads, if not using multithreading it is always 1 (since only 1 coroutine is used).
  	 * \see threadInfos
  	 * \see IsUsingMultithreading
  	 */
  	public static int NumParallelThreads {
  		get {
  			return threadInfos != null ? threadInfos.Length : 0;
  		}
  	}
  	
  	/** Returns whether or not multithreading is used.
  	 * \exception System.Exception Is thrown when it could not be decided if multithreading was used or not.
  	 * This should not happen if pathfinding is set up correctly.
  	 * \note This uses info about if threads are running right now, it does not use info from the settings on the A* object.
  	 */
  	public static bool IsUsingMultithreading {
  		get {
  			if (threads != null && threads.Length > 0)
  				return true;
  			else/* if (threads != null && threads.Length == 0 && threadEnumerator != null)*/
  				return false;
  			//else
  			//	throw new System.Exception ("Not 'using threading' and not 'not using threading'... Are you sure pathfinding is set up correctly?\nIf scripts are reloaded in unity editor during play this could happen.");
  		}
  	}
  	
  	/** Returns if any graph updates are waiting to be applied */
  	public bool IsAnyGraphUpdatesQueued { get { return graphUpdateQueue != null && graphUpdateQueue.Count > 0; }}
  	
  	private bool graphUpdateRoutineRunning = false;
  	
  	private bool isUpdatingGraphs = false;
  	private bool isRegisteredForUpdate = false;
  #endregion
  	
  #region Callbacks
  	/** @name Callbacks */
  	 /* Callbacks to pathfinding events.
  	 * These allow you to hook in to the pathfinding process.\n
  	 * Callbacks can be used like this:
  	 * \code
  	 * public void Start () {
  	 * 	AstarPath.OnPostScan += SomeFunction;
  	 * }
  	 * 
  	 * public void SomeFunction (AstarPath active) {
  	 * 	//This will be called every time the graphs are scanned
  	 * }
  	 * \endcode
  	*/
  	 /** @{ */
  	
  	/** Called on Awake before anything else is done.
  	  * This is called at the start of the Awake call, right after #active has been set, but this is the only thing that has been done.\n
  	  * Use this when you want to set up default settings for an AstarPath component created during runtime since some settings can only be changed in Awake
  	  * (such as multithreading related stuff)
  	  * \code
  	  * //Create a new AstarPath object on Start and apply some default settings
  	  * public void Start () {
  	  * 	AstarPath.OnAwakeSettings += ApplySettings;
  	  * 	AstarPath astar = AddComponent<AstarPath>();
  	  * }
  	  * 
  	  * public void ApplySettings () {
  	  * 	//Unregister from the delegate
  	  * 	AstarPath.OnAwakeSettings -= ApplySettings;
  	  * 	
  	  * 	//For example useMultithreading should not be changed after the Awake call
  	  * 	//so here's the only place to set it if you create the component during runtime
  	  * 	AstarPath.active.useMultithreading = true;
  	  * }
  	  * \endcode
  	  */
  	public static OnVoidDelegate OnAwakeSettings;
  	
  	public static OnGraphDelegate OnGraphPreScan; /**< Called for each graph before they are scanned */
  	
  	public static OnGraphDelegate OnGraphPostScan; /**< Called for each graph after they have been scanned. All other graphs might not have been scanned yet. */
  	
  	public static OnPathDelegate OnPathPreSearch; /**< Called for each path before searching. Be carefull when using multithreading since this will be called from a different thread. */
  	public static OnPathDelegate OnPathPostSearch; /**< Called for each path after searching. Be carefull when using multithreading since this will be called from a different thread. */
  	
  	public static OnScanDelegate OnPreScan; /**< Called before starting the scanning */
  	public static OnScanDelegate OnPostScan; /**< Called after scanning. This is called before applying links, flood-filling the graphs and other post processing. */
  	public static OnScanDelegate OnLatePostScan; /**< Called after scanning has completed fully. This is called as the last thing in the Scan function. */
  	
  	public static OnScanDelegate OnGraphsUpdated; /**< Called when any graphs are updated. Register to for example recalculate the path whenever a graph changes. */
  	
  	/** Called when \a pathID overflows 65536.
  	 * The Pathfinding.CleanupPath65K will be added to the queue, and directly after, this callback will be called.
  	 * \note This callback will be cleared every timed it is called, so if you want to register to it repeatedly, register to it directly on receiving the callback as well. 
  	 */
  	public static OnVoidDelegate On65KOverflow;
  	
  	/** Will send a callback when it is safe to update the nodes. Register to this with RegisterSafeNodeUpdate
  	 * When it is safe is defined as between the path searches.
  	 * This callback will only be sent once and is nulled directly after the callback is sent.
  	 * \warning Note that these callbacks are not thread safe when using multithreading, DO NOT call any part of the Unity API from these callbacks except for Debug.Log
  	 */
  	private static OnVoidDelegate OnSafeCallback;
  	
  	/** Will send a callback when it is safe to update the nodes. Register to this with RegisterThreadSafeNodeUpdate
  	 * When it is safe is defined as between the path searches.
  	 * This callback will only be sent once and is nulled directly after the callback is sent.
  	 * \see OnSafeCallback
  	 */
  	private static OnVoidDelegate OnThreadSafeCallback;
  	
  	/** Used to enable gizmos in editor scripts.
  	  * Used internally by the editor, do not use this in game code */
  	public OnVoidDelegate OnDrawGizmosCallback;
  	
  	public OnVoidDelegate OnGraphsWillBeUpdated;
  	public OnVoidDelegate OnGraphsWillBeUpdated2;
  	
  	/* @} */
  #endregion
  	
  #region MemoryStructures
  	
  	/** Stack containing all waiting graph update queries. Add to this stack by using \link UpdateGraphs \endlink
  	 * \see UpdateGraphs
  	 */
  	[System.NonSerialized]
  	public Queue<GraphUpdateObject> graphUpdateQueue;
  	
  	/** Stack used for flood-filling the graph. It is saved to minimize memory allocations. */
  	[System.NonSerialized]
  	public Stack<Node> floodStack;
  	
  	/** \todo Check scene switches */
  	public static Queue<Path> pathQueue = new Queue<Path> ();
  	
  	public static Thread[] threads;
  	
  	/** Holds info about each thread.
  	 * The first item will hold information about the pathfinding coroutine when not using multithreading.
  	 */
  	public static PathThreadInfo[] threadInfos;
  	
  	/** When no multithreading is used, the IEnumerator is stored here.
  	 * When no multithreading is used, a coroutine is used instead. It is not directly called with StartCoroutine
  	 * but a separate function has just a while loop which increments the main IEnumerator.
  	 * This is done so other functions can step the thread forward at any time, without having to wait for Unity to update it.
  	 * \see CalculatePaths
  	 * \see CalculatePathsHandler
  	 */
  	public static IEnumerator threadEnumerator;
  	public static Pathfinding.Util.LockFreeStack pathReturnStack = new Pathfinding.Util.LockFreeStack();
  	
  	/** Stack to hold paths waiting to be recycled */
  	public static Stack<Path> PathPool;
  	
  #endregion
  	
  	/** Shows or hides graph inspectors.
  	 * Used internally by the editor */
  	public bool showGraphs = false;
  	
  	/** The last area index which was used.
  	 * Used for the \link FloodFill(Node node) FloodFill \endlink function to start flood filling with an unused area.
  	 * \see FloodFill(Node node)
  	 */
  	public int lastUniqueAreaIndex = 0;
  	
  #region ThreadingMembers
  	
  	/** Flag set if there are paths to calculate.
  	 * Might get reset if a function wants to pause pathfinding (for example to update graphs)
  	 */
  	private static readonly ManualResetEvent pathQueueFlag = new ManualResetEvent (false);		/**< Thread flag, reset if there are no more paths in the queue */
  	private static readonly ManualResetEvent threadSafeUpdateFlag = new ManualResetEvent (false);	/**< Thread flag, reset while a thread wait for the Unity thread to call threadsafe updates */
  	private static readonly ManualResetEvent safeUpdateFlag = new ManualResetEvent (false);		/**< Thread flag, set if safe or thread safe updates need to be done */
  	private static bool threadSafeUpdateState = false;
  	private static readonly System.Object safeUpdateLock = new object();
  	private static bool doSetQueueState = true;
  	
  	/** Resets all event flags.
  	 * This should be called when resetting the static members of AstarPath.
  	 * \see OnDestroy
  	 */
  	private static void ResetQueueStates () {
  		pathQueueFlag.Reset ();
  		threadSafeUpdateFlag.Reset();
  		safeUpdateFlag.Reset();
  		threadSafeUpdateState = false;
  		doSetQueueState = true;
  	}
  	
  	/** This will trick threads to think there is more work to be done and then abort them gracefully.
  	 * When they think there is more work to be done, they will first test if new paths should be accepted, now they are not, so the threads will abort gracefully.
  	 * Only call this when you want to abort all threads. For example in the OnDestroy function.
  	 * After this function has been called, it's good to loop through all threads and Thread.Join them with some timeout.
  	 * If the timeout exceeds, you can call Thread.Abort on them
  	 * \see OnDestroy
  	 * \see acceptNewPaths
  	 */
  	private static void TrickAbortThreads () {
  		AstarPath.active.acceptNewPaths = false;
  		pathQueueFlag.Set();
  	}
  	
  #endregion
  	
  	/** Time the last graph update was done.
  	 * Used to group together frequent graph updates to batches */
  	private float lastGraphUpdate = -9999F;
  	
  	/** The next unused Path ID.
  	 * Incremented for every call to GetFromPathPool */
  	private ushort nextFreePathID = 1;
  	
  	/** Returns tag names.
  	 * Makes sure that the tag names array is not null and of length 32.
  	 * If it is null or not of length 32, it creates a new array and fills it with 0,1,2,3,4 etc...
  	 * \see AstarPath.FindTagNames
  	 */
  	public string[] GetTagNames () {
  		
  		if (tagNames == null || tagNames.Length	!= 32) {
  			tagNames = new string[32];
  			for (int i=0;i<tagNames.Length;i++) {
  				tagNames[i] = ""+i;
  			}
  			tagNames[0] = "Basic Ground";
  		}
  		return tagNames;
  	}
  	
  	/** Tries to find an AstarPath object and return tag names.
  	 * If an AstarPath object cannot be found, it returns an array of length 1 with an error message.
  	 * \see AstarPath.GetTagNames
  	 */
  	public static string[] FindTagNames () {
  		if (active != null) return active.GetTagNames ();
  		else {
  			AstarPath a = GameObject.FindObjectOfType (typeof (AstarPath)) as AstarPath;
  			if (a != null) { active = a; return a.GetTagNames (); }
  			else {
  				return new string[1] {"There is no AstarPath component in the scene"};
  			}
  		}
  	}
  	
  	/** Returns the next free path ID. If the next free path ID overflows 65535, a cleanup operation is queued
  	  * \see Pathfinding.CleanupPath65K */
  	public ushort GetNextPathID ()
  	{
  		if (nextFreePathID == 0) {
  			nextFreePathID++;
  			
  			//Queue a cleanup operation to zero all path IDs
  			//StartPath (new CleanupPath65K ());
  			Debug.Log ("65K cleanup");
  			
  			//ushort toBeReturned = nextFreePathID;
  			
  			if (On65KOverflow != null) {
  				OnVoidDelegate tmp = On65KOverflow;
  				On65KOverflow = null;
  				tmp ();
  			}
  			
  			//return nextFreePathID++;
  		}
  		return nextFreePathID++;
  	}
  	
  	
  	/** Calls OnDrawGizmos on graph generators and also #OnDrawGizmosCallback */
  	private void OnDrawGizmos () {
  		AstarProfiler.StartProfile ("OnDrawGizmos");
  		
  		if (active == null) {
  			active = this;
  		} else if (active != this) {
  			return;
  		}
  		
  		if (graphs == null) return;
  		
  		for (int i=0;i<graphs.Length;i++) {
  			if (graphs[i] == null) continue;
  			
  			if (graphs[i].drawGizmos)
  				graphs[i].OnDrawGizmos (showNavGraphs);
  		}
  		
  		if (showUnwalkableNodes && showNavGraphs) {
  			Gizmos.color = AstarColor.UnwalkableNode;
  			for (int i=0;i<graphs.Length;i++) {
  				if (graphs[i] == null || graphs[i].nodes == null) continue;
  				Node[] nodes = graphs[i].nodes;
  				for (int j=0;j<nodes.Length;j++) {
  					if (nodes[j] != null && !nodes[j].walkable) {
  						Gizmos.DrawCube ((Vector3)nodes[j].position, Vector3.one*unwalkableNodeDebugSize);
  					}
  				}
  			}
  		}
  		
  
gt: 		if (OnDrawGizmosCallback != null) {