public PathThreadInfo(int index, AstarPath astar, PathHandler runData) { this.threadIndex = index; this.astar = astar; this.runData = runData; this.lockObject = new object(); }
//This function will be called when the pathfinding is complete, it will be called when the pathfinding returned an error too. public void OnComplete (AstarPath.Path p) { //If the script was already calculating a path when a new path started calculating, then it would have canceled the first path, that will generate an OnComplete message from the first path, this makes sure we only get OnComplete messages from the path we started calculating latest. if (path != p) { return; } //What should we do if the path returned an error (there is no available path to the target). if (path.error) { switch (onError) { case OnError.None: return; case OnError.ErrorMessage: SendMessage("PathError",new Vector3[0],SendMessageOptions.DontRequireReceiver); break; case OnError.EmptyArray: SendMessage("PathComplete",new Vector3[0],SendMessageOptions.DontRequireReceiver); break; } return; } if (path.path == null) { Debug.LogError ("The 'Path' array is not assigned - System Error - Please send a bug report - Include the following info:\nError = "+p.error+"\nStart = "+startpos+"\nEnd = "+endpos+"\nFound End = "+p.foundEnd+"\nError = "+p.error); } if(path.path.Length > 1) { //Convert the Node array to a Vector3 array, subract one from the array if Remove First is true and add one to the array if Use Real End is set to Add Vector3[] a = new Vector3[path.path.Length - (removeFirst ? 1 : 0) + (endPoint == RealEnd.AddExact ? 1 : 0)]; for (int i=0;i<path.path.Length;i++) { //Ignore the first node if Remove First is set to True if (removeFirst && i==0) { continue; } a[i - (removeFirst ? 1 : 0)] = path.path[i].vectorPos; } if (startPoint == RealStart.Exact) { a[0] = startpos; } //Assign the endpoint if (endPoint == RealEnd.AddExact || endPoint == RealEnd.Exact) { a[a.Length-1] = endpos; } //Store the path in a variable so it can be drawn in the scene view for debugging pathPoints = a; //Send the Vector3 array to a movement script attached to this gameObject SendMessage("PathComplete",a,SendMessageOptions.DontRequireReceiver); } else { Vector3[] a2 = new Vector3[1] {(endPoint == RealEnd.AddExact || endPoint == RealEnd.Exact ? endpos : startpos)}; pathPoints = a2; SendMessage("PathComplete",a2,SendMessageOptions.DontRequireReceiver); } }
public PathThreadInfo(int index, AstarPath astar, NodeRunData runData) { this.threadIndex = index; this.astar = astar; this.runData = runData; _lock = new object(); }
void CreateGraph(AstarPath astar) { if (!points) { Debug.LogWarning("missing points root for autopointgraph " + name); } var graphs = new List<NavGraph>(astar.graphs); if (graphs.Contains(graph)) { return; } graph = new PointGraph(); graph.active = astar; graph.name = "AutoPointGraph (" + name + ")"; graph.root = points; graph.raycast = true; graph.maxDistance = 0; graph.recursive = true; graph.mask = -1; graphs.Add(graph); astar.graphs = graphs.ToArray(); }
protected override void Start() { base.Start(); if(Pathfinding == null) { Pathfinding = (AstarPath)GameObject.FindObjectOfType(typeof(AstarPath)); } }
/** Constructor for a graph node. */ protected GraphNode (AstarPath astar) { if (!System.Object.ReferenceEquals(astar, null)) { this.nodeIndex = astar.GetNewNodeIndex(); astar.InitializeNode(this); } else { throw new System.Exception("No active AstarPath object to bind to"); } }
private void InitializeAstarPath() { _astarPath = AstarPath.active; _astarPath.scanOnStartup = false; // IMPROVE max distance from a worldspace position to a node from my experimentation // assuming points surrounding obstacles are set at 0.05 grids away (0.5 * 0.1) from obstacle center // and interior sector points are 0.25 grids away from sector center (0.5 * 0.5) _astarPath.maxNearestNodeDistance = 600F; // TODO other settings }
// End of fallback /** Constructor for a graph node. */ public GraphNode (AstarPath astar) { //this.nodeIndex = NextNodeIndex++; if (astar != null) { this.nodeIndex = astar.GetNewNodeIndex(); astar.InitializeNode (this); } else { throw new System.Exception ("No active AstarPath object to bind to"); } }
private void OnGraphScansCompleted(AstarPath astarPath) { //if (GameManager.Instance.GameState == GameState.GeneratingPathGraphs) { //GameManager.Instance.__ProgressToRunning(); // TODO need to tell GameManager that it is OK to progress the game state // WARNING: I must not directly cause the game state to change as the other subscribers to // GameStateChanged may not have been called yet. This GraphScansCompletedEvent occurs // while we are still processing OnGameStateChanged //} }
int zFront = 0; //forward #endregion Fields #region Methods // Use this for initialization void Start() { dropDownMenuObject = GameObject.Find("Panel").GetComponent<DropDownMenu>(); missionReader = GameObject.FindGameObjectWithTag("Grid").GetComponent<MissionReader>(); astarPath = GameObject.FindGameObjectWithTag("Grid").GetComponent<AstarPath>(); xLeft = -27; xRight = 27; zFront = -110; zBack = -140; }
/// <summary> /// Editor only!!! /// </summary> public static void CreateGraphIfItNull(AstarPath path) { if (path == null) { Debug.LogWarning("AstarPath not found"); return; } if (path.astarData == null || path.astarData.gridGraph == null) AstarPath.MenuScan(); }
public void DoStuff() { if (!astarPath.IsNone && astarPath.Value != null) { astarp = FsmConverter.GetAstarPath(astarPath); } else { astarp = AstarPath.active; } if(!isScanning.IsNone) { isScanning.Value = astarp.isScanning; } if(!showGraphs.IsNone) { showGraphs.Value = astarp.showGraphs; } if(!IsUsingMultithreading.IsNone) { IsUsingMultithreading.Value = AstarPath.IsUsingMultithreading; } if(!IsAnyGraphUpdatesQueued.IsNone) { IsAnyGraphUpdatesQueued.Value = astarp.IsAnyGraphUpdatesQueued; } if(!lastUniqueAreaIndex.IsNone) { lastUniqueAreaIndex.Value = astarp.lastUniqueAreaIndex; } if(!ActiveThreadsCount.IsNone) { ActiveThreadsCount.Value = AstarPath.ActiveThreadsCount; } if(!NumParallelThreads.IsNone) { NumParallelThreads.Value = AstarPath.NumParallelThreads; } if(!Version.IsNone) { Version.Value = AstarPath.Version.ToString(); } if(!graphs.IsNone) { graphs.Value = FsmConverter.SetNavGraphs(astarp.graphs); } if(!activeAstarPath.IsNone) { activeAstarPath.Value = FsmConverter.SetAstarPath(AstarPath.active); } if (!astarData.IsNone) { astarData.Value = FsmConverter.SetNavGraphs(astarp.graphs); } return; }
public void DoStuff() { if (!astarPath.IsNone && astarPath.Value != null) { astarp = FsmConverter.GetAstarPath(astarPath); } else { astarp = AstarPath.active; } if(!isScanning.IsNone) { astarp.isScanning = isScanning.Value; } if(!showGraphs.IsNone) { astarp.showGraphs = showGraphs.Value; } if(!lastUniqueAreaIndex.IsNone) { astarp.lastUniqueAreaIndex = lastUniqueAreaIndex.Value; } if (!astarData.IsNone) { astarp.graphs = FsmConverter.GetNavGraphs(astarData.Value); } return; }
public PathProcessor (AstarPath astar, PathReturnQueue returnQueue, int processors, bool multithreaded) { this.astar = astar; this.returnQueue = returnQueue; if (processors < 0) { throw new System.ArgumentOutOfRangeException("processors"); } if (!multithreaded && processors != 1) { throw new System.Exception("Only a single non-multithreaded processor is allowed"); } // Set up path queue with the specified number of receivers queue = new ThreadControlQueue(processors); threadInfos = new PathThreadInfo[processors]; for (int i = 0; i < processors; i++) { threadInfos[i] = new PathThreadInfo(i, astar, new PathHandler(i, processors)); } if (multithreaded) { threads = new Thread[processors]; // Start lots of threads for (int i = 0; i < processors; i++) { var threadIndex = i; var thread = new Thread (() => CalculatePathsThreaded(threadInfos[threadIndex])); thread.Name = "Pathfinding Thread " + i; thread.IsBackground = true; threads[i] = thread; thread.Start(); } } else { // Start coroutine if not using multithreading threadCoroutine = CalculatePaths(threadInfos[0]); } }
/** Auto links grid graphs together. Called after all graphs have been scanned. * \see autoLinkGrids */ public void OnPostScan (AstarPath script) { AstarPath.OnPostScan -= new OnScanDelegate (OnPostScan); if (!autoLinkGrids || autoLinkDistLimit <= 0) { return; } //Link to other grids throw new System.NotSupportedException (); #if FALSE int maxCost = Mathf.RoundToInt (autoLinkDistLimit * Int3.Precision); //Loop through all GridGraphs foreach (GridGraph gg in script.astarData.FindGraphsOfType (typeof (GridGraph))) { if (gg == this || gg.nodes == null || nodes == null) { continue; } //Int3 prevPos = gg.GetNearest (nodes[0]).position; //Z = 0 for (int x = 0; x < width;x++) { GraphNode node1 = nodes[x]; GraphNode node2 = gg.GetNearest ((Vector3)node1.Position).node; Vector3 pos = inverseMatrix.MultiplyPoint3x4 ((Vector3)node2.Position); if (pos.z > 0) { continue; } int cost = (node1.Position-node2.Position).costMagnitude; if (cost > maxCost) { continue; } node1.AddConnection (node2,cost); node2.AddConnection (node1,cost); } //X = 0 for (int z = 0; z < depth;z++) { GraphNode node1 = nodes[z*width]; GraphNode node2 = gg.GetNearest ((Vector3)node1.Position).node; Vector3 pos = inverseMatrix.MultiplyPoint3x4 ((Vector3)node2.Position); if (pos.x > 0) { continue; } int cost = (node1.Position-node2.Position).costMagnitude; if (cost > maxCost) { continue; } node1.AddConnection (node2,cost); node2.AddConnection (node1,cost); } //Z = max for (int x = 0; x < width;x++) { GraphNode node1 = nodes[(depth-1)*width+x]; GraphNode node2 = gg.GetNearest ((Vector3)node1.Position).node; Vector3 pos = inverseMatrix.MultiplyPoint3x4 ((Vector3)node2.Position); if (pos.z < depth-1) { continue; } //Debug.DrawLine (node1.position,node2.position,Color.red); int cost = (node1.Position-node2.Position).costMagnitude; if (cost > maxCost) { continue; } node1.AddConnection (node2,cost); node2.AddConnection (node1,cost); } //X = max for (int z = 0; z < depth;z++) { GraphNode node1 = nodes[z*width+width-1]; GraphNode node2 = gg.GetNearest ((Vector3)node1.Position).node; Vector3 pos = inverseMatrix.MultiplyPoint3x4 ((Vector3)node2.Position); if (pos.x < width-1) { continue; } int cost = (node1.Position-node2.Position).costMagnitude; if (cost > maxCost) { continue; } node1.AddConnection (node2,cost); node2.AddConnection (node1,cost); } } #endif }
public static AstarSerializer GetDeserializer(Version version, AstarPath script) { if (version == AstarPath.Version) { return new AstarSerializer (script); } else if (version > AstarPath.Version) { //Higher version, trying to load return new AstarSerializer (script); } else { //Load older version if (version >= new Version (3,0,7)) { return new AstarSerializer3_07 (script); } else if (version >= new Version (3,0,5)) { return new AstarSerializer3_05 (script); } else if (version >= new Version (3,0,4)) { return new AstarSerializer3_04 (script); } else { return new AstarSerializer3_01 (script); } /*if (version > new Version (3,0,1)) { return new AstarSerializer3_04 (script); } else { return new AstarSerializer3_01 (script); }*/ } }
/** Deserializes nodes in the graph. The deserialized nodes will be created using graph.CreateNodes (numberOfNodes). * \astarpro */ public void DeserializeNodes(NavGraph graph, NavGraph[] graphs, int graphIndex, AstarPath active) { if (mask == SMask.SaveNodes) { ISerializableGraph serializeGraph = graph as ISerializableGraph; if (serializeGraph == null) { Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType()); return; } int numNodes = readerStream.ReadInt32 (); graph.nodes = serializeGraph.CreateNodes (numNodes); if (numNodes == 0) { return; } for (int i=0;i<graph.nodes.Length;i++) { graph.nodes[i].graphIndex = graphIndex; } Debug.Log ("Loading "+numNodes+ " nodes"); if (!MoveToVariableAnchor ("DeserializeGraphNodes")) { Debug.LogError ("Error loading nodes - Couldn't find anchor"); } serializeGraph.DeSerializeNodes (graph.nodes,this); if (!MoveToVariableAnchor ("DeserializeNodes")) { Debug.LogError ("Error loading nodes - Couldn't find anchor"); return; } if (mask == SMask.RunLengthEncoding) { int totalCount = 0; //Penalties while (totalCount < graph.nodes.Length) { int runLength = (int)readerStream.ReadByte (); int value = readerStream.ReadInt32 (); int endIndex = totalCount+runLength; if (endIndex > graph.nodes.Length) { Debug.LogError ("Run Length Encoding is too long "+runLength+" "+endIndex+ " "+graph.nodes.Length+" "+totalCount); endIndex = graph.nodes.Length; } for (int i=totalCount;i<endIndex;i++) { graph.nodes[i].penalty = (uint)value; } totalCount = endIndex; } totalCount = 0; //Flags while (totalCount < graph.nodes.Length) { int runLength = (int)readerStream.ReadByte (); int value = readerStream.ReadInt32 (); int endIndex = totalCount+runLength; if (endIndex > graph.nodes.Length) { Debug.LogError ("Run Length Encoding is too long "+runLength+" "+endIndex+ " "+graph.nodes.Length+" "+totalCount); endIndex = graph.nodes.Length; } for (int i=totalCount;i<endIndex;i++) { graph.nodes[i].flags = value; } totalCount += runLength; } } for (int i=0;i<graph.nodes.Length;i++) { DeSerializeNode (graph.nodes[i], graphs, graphIndex, readerStream); } } }
// Use this for initialization public void Start() { if (isPlayer) { // init standard variables movementRadius = 4f; position = transform.position; members = new List <Transform>() { transform }; StartCoroutine(UpdateSquad()); return; } // Add members members = new List <Transform>(); for (int i = 0; i < transform.childCount; i++) { members.Add(transform.GetChild(i)); } // Set team foreach (Transform t in members) { Entity entity = t.GetComponent <Entity>(); entity.team = team; if (t.GetComponent <Moving>() == null) { mobile = false; } } // Calculate position { // Squad position is the average of its members position position = new Vector2(0, 0); foreach (Transform t in members) { position.x += t.position.x; position.y += t.position.y; } position /= members.Count; } // Calculate values movementRadius = movementRadiusMultiplier * Mathf.Sqrt(members.Count); CalcCombatPower(); // Start update sequence except when in edit movementMode bool avoid = false; #if UNITY_EDITOR avoid = !EditorApplication.isPlaying; #endif if (!avoid) { StartCoroutine(UpdateSquad()); } // Calculate max health maxHealth = 0; foreach (Transform member in members) { maxHealth += member.GetComponent <Entity>().maxHealth; } // Inits bloodlust = bloodlustMultiplier; aStarPath = aStar.GetComponent <AstarPath>(); squadsInCombatWith = new List <Squad>(); }
public AstarSerializer(AstarPath script) { active = script; astarData = script.astarData; mask = -1; mask -= SMask.SaveNodes; }
public override void OnInspectorGUI() { GraphUpdateScene script = target as GraphUpdateScene; if (script.points == null) { script.points = new Vector3[0]; } Vector3[] prePoints = script.points; DrawDefaultInspector(); EditorGUI.indentLevel = 1; if (prePoints != script.points) { script.RecalcConvex(); HandleUtility.Repaint(); } bool preConvex = script.convex; script.convex = EditorGUILayout.Toggle(new GUIContent("Convex", "Sets if only the convex hull of the points should be used or the whole polygon"), script.convex); if (script.convex != preConvex) { script.RecalcConvex(); HandleUtility.Repaint(); } script.minBoundsHeight = EditorGUILayout.FloatField(new GUIContent("Min Bounds Height", "Defines a minimum height to be used for the bounds of the GUO.\nUseful if you define points in 2D (which would give height 0)"), script.minBoundsHeight); script.applyOnStart = EditorGUILayout.Toggle("Apply On Start", script.applyOnStart); script.applyOnScan = EditorGUILayout.Toggle("Apply On Scan", script.applyOnScan); script.modifyWalkability = EditorGUILayout.Toggle("Modify walkability", script.modifyWalkability); if (script.modifyWalkability) { EditorGUI.indentLevel++; script.setWalkability = EditorGUILayout.Toggle("Walkability", script.setWalkability); EditorGUI.indentLevel--; } script.penaltyDelta = EditorGUILayout.IntField("Penalty Delta", script.penaltyDelta); if (script.penaltyDelta < 0) { GUILayout.Label("Be careful when lowering the penalty. Negative penalties are not supported and will instead underflow and get really high.", "HelpBox"); } bool worldSpace = EditorGUILayout.Toggle(new GUIContent("Use World Space", "Specify coordinates in world space or local space. When using local space you can move the GameObject around and the points will follow" ), script.useWorldSpace); if (worldSpace != script.useWorldSpace) { script.ToggleUseWorldSpace(); } script.modifyTag = EditorGUILayout.Toggle(new GUIContent("Modify Tags", "Should the tags of the nodes be modified"), script.modifyTag); if (script.modifyTag) { EditorGUI.indentLevel++; script.setTag = EditorGUILayout.Popup("Set Tag", script.setTag, AstarPath.FindTagNames()); EditorGUI.indentLevel--; } //GUI.color = Color.red; if (GUILayout.Button("Tags can be used to restrict which units can walk on what ground. Click here for more info", "HelpBox")) { Application.OpenURL(AstarPathEditor.GetURL("tags")); } //GUI.color = Color.white; EditorGUILayout.Separator(); //GUILayout.Space (0); //GUI.Toggle (r,script.lockToY,"","Button"); script.lockToY = EditorGUILayout.Toggle("Lock to Y", script.lockToY); if (script.lockToY) { EditorGUI.indentLevel++; script.lockToYValue = EditorGUILayout.FloatField("Lock to Y value", script.lockToYValue); EditorGUI.indentLevel--; script.LockToY(); } EditorGUILayout.Separator(); if (GUI.changed) { Undo.RegisterUndo(script, "Modify Settings on GraphUpdateObject"); EditorUtility.SetDirty(target); } if (GUILayout.Button("Clear all points")) { Undo.RegisterUndo(script, "Removed All Points"); script.points = new Vector3[0]; script.RecalcConvex(); } }
/** Called on graph rescanning, updates the current node */ private void OnRescan(AstarPath active) { Teleport(); Debug.LogWarning("[NavmeshController.cs] On Rescan"); }
public AstarSerializer3_07(AstarPath script) : base(script) { }
protected MeshNode(AstarPath astar) : base(astar) { }
public override void OnInspectorGUI() { DrawDefaultInspector(); var script = target as Seeker; Undo.RecordObject(script, "modify settings on Seeker"); // Show a dropdown selector for the tags that this seeker can traverse // A callback is necessary because Unity's GenericMenu uses callbacks EditorGUILayoutx.TagMaskField(new GUIContent("Valid Tags"), script.traversableTags, result => script.traversableTags = result); #if !ASTAR_NoTagPenalty EditorGUI.indentLevel = 0; tagPenaltiesOpen = EditorGUILayout.Foldout(tagPenaltiesOpen, new GUIContent("Tag Penalties", "Penalties for each tag")); if (tagPenaltiesOpen) { EditorGUI.indentLevel = 2; string[] tagNames = AstarPath.FindTagNames(); for (int i = 0; i < script.tagPenalties.Length; i++) { int tmp = EditorGUILayout.IntField((i < tagNames.Length ? tagNames[i] : "Tag " + i), (int)script.tagPenalties[i]); if (tmp < 0) { tmp = 0; } // If the new value is different than the old one // Update the value and mark the script as dirty if (script.tagPenalties[i] != tmp) { script.tagPenalties[i] = tmp; EditorUtility.SetDirty(target); } } if (GUILayout.Button("Edit Tag Names...")) { AstarPathEditor.EditTags(); } } EditorGUI.indentLevel = 1; #endif //Do some loading and checking if (!AstarPathEditor.stylesLoaded) { AstarPathEditor.LoadStyles(); } GUIStyle helpBox = GUI.skin.GetStyle("helpBox"); if (mods == null) { mods = new List <IPathModifier>(script.GetComponents <MonoModifier>() as IPathModifier[]); } else { mods.Clear(); mods.AddRange(script.GetComponents <MonoModifier>() as IPathModifier[]); } mods.Add(script.startEndModifier); bool changed = true; while (changed) { changed = false; for (int i = 0; i < mods.Count - 1; i++) { if (mods[i].Priority < mods[i + 1].Priority) { IPathModifier tmp = mods[i + 1]; mods[i + 1] = mods[i]; mods[i] = tmp; changed = true; } } } for (int i = 0; i < mods.Count; i++) { if (mods.Count - i != mods[i].Priority) { mods[i].Priority = mods.Count - i; GUI.changed = true; EditorUtility.SetDirty(target); SetModifierDirty(mods[i]); } } bool modifierErrors = false; IPathModifier prevMod = mods[0]; //Loops through all modifiers and checks if there are any errors in converting output between modifiers for (int i = 1; i < mods.Count; i++) { var monoMod = mods[i] as MonoModifier; if ((prevMod as MonoModifier) != null && !(prevMod as MonoModifier).enabled) { if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } continue; } if ((monoMod == null || monoMod.enabled) && prevMod != mods[i] && !ModifierConverter.CanConvert(prevMod.output, mods[i].input)) { modifierErrors = true; } if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } } EditorGUI.indentLevel = 0; modifiersOpen = EditorGUILayout.Foldout(modifiersOpen, "Modifiers Priorities" + (modifierErrors ? " - Errors in modifiers!" : "")); if (modifiersOpen) { if (GUILayout.Button("Modifiers attached to this gameObject are listed here.\nModifiers with a higher priority (higher up in the list) will be executed first.\nClick here for more info", helpBox)) { Application.OpenURL(AstarUpdateChecker.GetURL("modifiers")); } EditorGUILayout.HelpBox("Original or All can be converted to anything\n" + "NodePath can be converted to VectorPath\n" + "VectorPath can only be used as VectorPath\n" + "Vector takes both VectorPath and StrictVectorPath\n" + "Strict... can be converted to the non-strict variant", MessageType.None); prevMod = mods[0]; for (int i = 0; i < mods.Count; i++) { var monoMod = mods[i] as MonoModifier; Color prevCol = GUI.color; if (monoMod != null && !monoMod.enabled) { GUI.color *= new Color(1, 1, 1, 0.5F); } GUILayout.BeginVertical(GUI.skin.box); if (i > 0) { if ((prevMod as MonoModifier) != null && !(prevMod as MonoModifier).enabled) { prevMod = mods[i]; } else { if ((monoMod == null || monoMod.enabled) && !ModifierConverter.CanConvert(prevMod.output, mods[i].input)) { //GUILayout.BeginHorizontal (); //GUILayout.Space (28); GUIUtilityx.SetColor(new Color(0.8F, 0, 0)); GUILayout.Label("Cannot convert " + prevMod.GetType().Name + "'s output to " + mods[i].GetType().Name + "'s input\nRearranging the modifiers might help", EditorStyles.whiteMiniLabel); GUIUtilityx.ResetColor(); //GUILayout.EndHorizontal (); } if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } } } GUILayout.Label("Input: " + mods[i].input, EditorStyles.wordWrappedMiniLabel); int newPrio = EditorGUILayoutx.UpDownArrows(new GUIContent(ObjectNames.NicifyVariableName(mods[i].GetType().ToString())), mods[i].Priority, EditorStyles.label, AstarPathEditor.upArrow, AstarPathEditor.downArrow); GUILayout.Label("Output: " + mods[i].output, EditorStyles.wordWrappedMiniLabel); GUILayout.EndVertical(); int diff = newPrio - mods[i].Priority; if (i > 0 && diff > 0) { mods[i - 1].Priority = mods[i].Priority; SetModifierDirty(mods[i - 1]); } else if (i < mods.Count - 1 && diff < 0) { mods[i + 1].Priority = mods[i].Priority; SetModifierDirty(mods[i + 1]); } if (mods[i].Priority != newPrio) { mods[i].Priority = newPrio; SetModifierDirty(mods[i]); } GUI.color = prevCol; } EditorGUI.indentLevel -= 2; } if (GUI.changed) { EditorUtility.SetDirty(target); } }
public void Start() { astar = AstarPath.active; }
void Awake() { PathComponent = GetComponent <AstarPath>(); TileStorageComponent = Target.GetComponent <TileStorage>(); }
public void OnGUI() { if (!show || (!Application.isPlaying && !showInEditor)) { return; } if (style == null) { style = new GUIStyle(); style.normal.textColor = Color.white; style.padding = new RectOffset(5, 5, 5, 5); } if (Time.realtimeSinceStartup - lastUpdate > 0.2f || cachedText == null || !Application.isPlaying) { lastUpdate = Time.timeSinceLevelLoad; boxRect = new Rect(5, yOffset, 310, 40); text.Length = 0; text.AppendLine("A* Pathfinding Project Debugger"); text.Append("A* Version: ").Append(AstarPath.Version.ToString()); if (showMemProfile) { boxRect.height += 200; text.AppendLine(); text.AppendLine(); text.Append("Currently allocated".PadRight(25)); text.Append((allocMem / 1000000F).ToString("0.0 MB")); text.AppendLine(); text.Append("Peak allocated".PadRight(25)); text.Append((peakAlloc / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Last collect peak".PadRight(25)); text.Append((collectAlloc / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Allocation rate".PadRight(25)); text.Append((allocRate / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Collection frequency".PadRight(25)); text.Append(delta.ToString("0.00")); text.Append("s\n"); text.Append("Last collect fps".PadRight(25)); text.Append((1F / lastDeltaTime).ToString("0.0 fps")); text.Append(" ("); text.Append(lastDeltaTime.ToString("0.000 s")); text.Append(")"); } if (showFPS) { text.AppendLine(); text.AppendLine(); text.Append("FPS".PadRight(25)).Append((1F / delayedDeltaTime).ToString("0.0 fps")); float minFps = Mathf.Infinity; for (int i = 0; i < fpsDrops.Length; i++) { if (fpsDrops[i] < minFps) { minFps = fpsDrops[i]; } } text.AppendLine(); text.Append(("Lowest fps (last " + fpsDrops.Length + ")").PadRight(25)).Append(minFps.ToString("0.0")); } if (showPathProfile) { AstarPath astar = AstarPath.active; text.AppendLine(); if (astar == null) { text.Append("\nNo AstarPath Object In The Scene"); } else { if (Pathfinding.Util.ListPool <Vector3> .GetSize() > maxVecPool) { maxVecPool = Pathfinding.Util.ListPool <Vector3> .GetSize(); } if (Pathfinding.Util.ListPool <Pathfinding.Node> .GetSize() > maxNodePool) { maxNodePool = Pathfinding.Util.ListPool <Pathfinding.Node> .GetSize(); } text.Append("\nPool Sizes (size/total created)"); for (int i = 0; i < debugTypes.Length; i++) { debugTypes[i].Print(text); } } } cachedText = text.ToString(); } if (font != null) { style.font = font; style.fontSize = fontSize; } boxRect.height = style.CalcHeight(new GUIContent(cachedText), boxRect.width); GUI.Box(boxRect, ""); GUI.Label(boxRect, cachedText, style); }
public ParallelWorkQueue(Queue <T> queue) { this.queue = queue; initialCount = queue.Count; threadCount = System.Math.Min(initialCount, System.Math.Max(1, AstarPath.CalculateThreadCount(ThreadCount.AutomaticHighLoad))); }
private void Start() { _pathfinding = GetComponent <AstarPath>(); _gg = _pathfinding.data.gridGraph; }
public override void OnInspectorGUI() { DrawDefaultInspector(); Seeker script = target as Seeker; EditorGUILayoutx.SetTagField(new GUIContent("Valid Tags", "Sets which tags are traversable. Tags can be used to restrict which units can traverse which ground"), ref script.traversableTags); EditorGUI.indentLevel = 0; tagPenaltiesOpen = EditorGUILayout.Foldout(tagPenaltiesOpen, new GUIContent("Tag Penalties", "Penalties for each tag")); if (tagPenaltiesOpen) { EditorGUI.indentLevel = 2; string[] tagNames = AstarPath.FindTagNames(); for (int i = 0; i < script.tagPenalties.Length; i++) { int tmp = EditorGUILayout.IntField((i < tagNames.Length ? tagNames[i] : "Tag " + i), (int)script.tagPenalties[i]); if (tmp < 0) { tmp = 0; } script.tagPenalties[i] = tmp; } if (GUILayout.Button("Edit Tags...")) { AstarPathEditor.EditTags(); } } EditorGUI.indentLevel = 1; //Do some loading and checking if (!AstarPathEditor.stylesLoaded) { if (!AstarPathEditor.LoadStyles()) { if (AstarPathEditor.upArrow == null) { AstarPathEditor.upArrow = GUI.skin.FindStyle("Button"); AstarPathEditor.downArrow = AstarPathEditor.upArrow; } } else { AstarPathEditor.stylesLoaded = true; } } GUIStyle helpBox = GUI.skin.GetStyle("helpBox"); if (mods == null) { mods = new List <IPathModifier>(script.GetComponents <MonoModifier>() as IPathModifier[]); } else { mods.Clear(); mods.AddRange(script.GetComponents <MonoModifier>() as IPathModifier[]); } mods.Add(script.startEndModifier as IPathModifier); bool changed = true; while (changed) { changed = false; for (int i = 0; i < mods.Count - 1; i++) { if (mods[i].Priority < mods[i + 1].Priority) { IPathModifier tmp = mods[i + 1]; mods[i + 1] = mods[i]; mods[i] = tmp; changed = true; } } } for (int i = 0; i < mods.Count; i++) { if (mods.Count - i != mods[i].Priority) { mods[i].Priority = mods.Count - i; GUI.changed = true; EditorUtility.SetDirty(target); } } bool modifierErrors = false; IPathModifier prevMod = mods[0]; //Loops through all modifiers and checks if there are any errors in converting output between modifiers for (int i = 1; i < mods.Count; i++) { MonoModifier monoMod = mods[i] as MonoModifier; if ((prevMod as MonoModifier) != null && !(prevMod as MonoModifier).enabled) { if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } continue; } if ((monoMod == null || monoMod.enabled) && prevMod != mods[i] && !ModifierConverter.CanConvert(prevMod.output, mods[i].input)) { modifierErrors = true; } if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } } EditorGUI.indentLevel = 0; modifiersOpen = EditorGUILayout.Foldout(modifiersOpen, "Modifiers Priorities" + (modifierErrors ? " - Errors in modifiers!" : ""), EditorStyles.foldout); EditorGUI.indentLevel = 1; if (modifiersOpen) { EditorGUI.indentLevel += 2; //GUILayout.BeginHorizontal (); //GUILayout.Space (28); if (GUILayout.Button("Modifiers attached to this gameObject are listed here.\nModifiers with a higher priority (higher up in the list) will be executed first.\nClick here for more info", helpBox)) { Application.OpenURL(AstarPathEditor.GetURL("modifiers")); } //GUILayout.EndHorizontal (); prevMod = mods[0]; for (int i = 0; i < mods.Count; i++) { //EditorGUILayout.LabelField (mods[i].GetType ().ToString (),mods[i].Priority.ToString ()); MonoModifier monoMod = mods[i] as MonoModifier; Color prevCol = GUI.color; if (monoMod != null && !monoMod.enabled) { GUI.color *= new Color(1, 1, 1, 0.5F); } GUILayout.BeginVertical(GUI.skin.box); if (i > 0) { if ((prevMod as MonoModifier) != null && !(prevMod as MonoModifier).enabled) { prevMod = mods[i]; } else { if ((monoMod == null || monoMod.enabled) && !ModifierConverter.CanConvert(prevMod.output, mods[i].input)) { //GUILayout.BeginHorizontal (); //GUILayout.Space (28); GUIUtilityx.SetColor(new Color(0.8F, 0, 0)); GUILayout.Label("Cannot convert " + prevMod.GetType().Name + "'s output to " + mods[i].GetType().Name + "'s input\nRearranging the modifiers might help", EditorStyles.whiteMiniLabel); GUIUtilityx.ResetColor(); //GUILayout.EndHorizontal (); } if (monoMod == null || monoMod.enabled) { prevMod = mods[i]; } } } GUILayout.Label("Input: " + mods[i].input, EditorStyles.wordWrappedMiniLabel); int newPrio = EditorGUILayoutx.UpDownArrows(new GUIContent(ObjectNames.NicifyVariableName(mods[i].GetType().ToString())), mods[i].Priority, EditorStyles.label, AstarPathEditor.upArrow, AstarPathEditor.downArrow); GUILayout.Label("Output: " + mods[i].output, EditorStyles.wordWrappedMiniLabel); GUILayout.EndVertical(); int diff = newPrio - mods[i].Priority; if (i > 0 && diff > 0) { mods[i - 1].Priority = mods[i].Priority; } else if (i < mods.Count - 1 && diff < 0) { mods[i + 1].Priority = mods[i].Priority; } mods[i].Priority = newPrio; GUI.color = prevCol; } EditorGUI.indentLevel -= 2; } }
public void RecalculatePath(AstarPath astar) { this.graphsBeingUpdated = false; }
public override void OnInspectorGUI() { GraphUpdateScene script = target as GraphUpdateScene; if (script.points == null) { script.points = new Vector3[0]; } Vector3[] prePoints = script.points; DrawDefaultInspector(); EditorGUI.indentLevel = 1; if (prePoints != script.points) { script.RecalcConvex(); HandleUtility.Repaint(); } bool preConvex = script.convex; script.convex = EditorGUILayout.Toggle(new GUIContent("Convex", "Sets if only the convex hull of the points should be used or the whole polygon"), script.convex); if (script.convex != preConvex) { script.RecalcConvex(); HandleUtility.Repaint(); } script.applyOnStart = EditorGUILayout.Toggle("Apply On Start", script.applyOnStart); script.applyOnScan = EditorGUILayout.Toggle("Apply On Scan", script.applyOnScan); script.modifyWalkability = EditorGUILayout.Toggle("Modify walkability", script.modifyWalkability); if (script.modifyWalkability) { EditorGUI.indentLevel++; script.setWalkability = EditorGUILayout.Toggle("Walkability", script.setWalkability); EditorGUI.indentLevel--; } script.penalty = EditorGUILayout.IntField("Penalty", script.penalty); script.modifyTag = EditorGUILayout.Toggle(new GUIContent("Modify Tags", "Should the tags of the nodes be modified"), script.modifyTag); if (script.modifyTag) { EditorGUI.indentLevel++; script.setTag = EditorGUILayout.Popup("Set Tag", script.setTag, AstarPath.FindTagNames()); EditorGUI.indentLevel--; } //GUI.color = Color.red; if (GUILayout.Button("Tags can be used to restrict which units can walk on what ground. Click here for more info", "HelpBox")) { Application.OpenURL(AstarPathEditor.GetURL("tags")); } //GUI.color = Color.white; if (GUILayout.Button("Clear all points")) { Undo.RegisterUndo(script, "Removed All Points"); script.points = new Vector3[0]; script.RecalcConvex(); } if (GUI.changed) { EditorUtility.SetDirty(target); } }
/** Starts a path specified by PathTypesDemo.activeDemo */ void DemoPath() { Path p = null; switch (activeDemo) { case DemoMode.ABPath: //Good Game //p = ABPath.Construct(start.position, end.position, OnPathComplete); p = ABPath.Construct((VInt3)start.position, (VInt3)end.position, OnPathComplete); break; case DemoMode.MultiTargetPath: StartCoroutine(DemoMultiTargetPath()); break; case DemoMode.ConstantPath: StartCoroutine(DemoConstantPath()); break; case DemoMode.RandomPath: //Good Game //RandomPath rp = RandomPath.Construct(start.position, searchLength, OnPathComplete); RandomPath rp = RandomPath.Construct((VInt3)start.position, searchLength, OnPathComplete); rp.spread = spread; rp.aimStrength = aimStrength; //Good Game //rp.aim = end.position; rp.aim = (VInt3)end.position; p = rp; break; case DemoMode.FleePath: //Good Game //FleePath fp = FleePath.Construct(start.position, end.position, searchLength, OnPathComplete); FleePath fp = FleePath.Construct((VInt3)start.position, (VInt3)end.position, searchLength, OnPathComplete); fp.aimStrength = aimStrength; fp.spread = spread; p = fp; break; case DemoMode.FloodPath: //Good Game //p = lastFloodPath = FloodPath.Construct(end.position, null); p = lastFloodPath = FloodPath.Construct((VInt3)end.position, null); break; case DemoMode.FloodPathTracer: if (lastFloodPath != null) { //Good Game //FloodPathTracer fpt = FloodPathTracer.Construct(end.position, lastFloodPath, OnPathComplete); FloodPathTracer fpt = FloodPathTracer.Construct((VInt3)end.position, lastFloodPath, OnPathComplete); p = fpt; } break; } if (p != null) { AstarPath.StartPath(p); lastPath = p; } }
private void DemoPath() { Path path = null; if (this.activeDemo == PathTypesDemo.DemoMode.ABPath) { path = ABPath.Construct(this.start.position, this.end.position, new OnPathDelegate(this.OnPathComplete)); if (this.agents != null && this.agents.Length > 0) { List <Vector3> list = ListPool <Vector3> .Claim(this.agents.Length); Vector3 vector = Vector3.zero; for (int i = 0; i < this.agents.Length; i++) { list.Add(this.agents[i].transform.position); vector += list[i]; } vector /= (float)list.Count; for (int j = 0; j < this.agents.Length; j++) { List <Vector3> list2; List <Vector3> expr_B8 = list2 = list; int index; int expr_BD = index = j; Vector3 a = list2[index]; expr_B8[expr_BD] = a - vector; } PathUtilities.GetPointsAroundPoint(this.end.position, AstarPath.active.graphs[0] as IRaycastableGraph, list, 0f, 0.2f); for (int k = 0; k < this.agents.Length; k++) { if (!(this.agents[k] == null)) { this.agents[k].target.position = list[k]; this.agents[k].UpdatePath(); } } } } else if (this.activeDemo == PathTypesDemo.DemoMode.MultiTargetPath) { MultiTargetPath multiTargetPath = MultiTargetPath.Construct(this.multipoints.ToArray(), this.end.position, null, new OnPathDelegate(this.OnPathComplete)); path = multiTargetPath; } else if (this.activeDemo == PathTypesDemo.DemoMode.RandomPath) { RandomPath randomPath = RandomPath.Construct(this.start.position, this.searchLength, new OnPathDelegate(this.OnPathComplete)); randomPath.spread = this.spread; randomPath.aimStrength = this.aimStrength; randomPath.aim = this.end.position; path = randomPath; } else if (this.activeDemo == PathTypesDemo.DemoMode.FleePath) { FleePath fleePath = FleePath.Construct(this.start.position, this.end.position, this.searchLength, new OnPathDelegate(this.OnPathComplete)); fleePath.aimStrength = this.aimStrength; fleePath.spread = this.spread; path = fleePath; } else if (this.activeDemo == PathTypesDemo.DemoMode.ConstantPath) { base.StartCoroutine(this.CalculateConstantPath()); path = null; } else if (this.activeDemo == PathTypesDemo.DemoMode.FloodPath) { FloodPath floodPath = FloodPath.Construct(this.end.position, null); this.lastFlood = floodPath; path = floodPath; } else if (this.activeDemo == PathTypesDemo.DemoMode.FloodPathTracer && this.lastFlood != null) { FloodPathTracer floodPathTracer = FloodPathTracer.Construct(this.end.position, this.lastFlood, new OnPathDelegate(this.OnPathComplete)); path = floodPathTracer; } if (path != null) { AstarPath.StartPath(path, false); this.lastPath = path; } }
public void initMap() { //关卡阶段 level = GameManager.Instance.sceneLevel / 5; if (GameManager.Instance.sceneLevel == 5) { AudioManager.Instance.StopPlayBGM(); } //创建地板和围墙 if (mapholder != null) { Destroy(mapholder.gameObject); mapholder = null; } mapholder = new GameObject("Map").transform; for (int i = 0; i < xLength; i++) { for (int j = 0; j < yLength; j++) { if (i == 0 || j == 0 || i == xLength - 1 || j == yLength - 1) { GameObject go = GameObject.Instantiate(wall[1], new Vector3(i, j, 0), Quaternion.identity); go.transform.SetParent(mapholder); } else { GameObject go = GameObject.Instantiate(floor, new Vector3(i, j, 0), Quaternion.identity); go.transform.SetParent(mapholder); } } } positionList.Clear(); for (int x = 1; x < xLength - 1; x++) { for (int y = 1; y < yLength - 1; y++) { positionList.Add(new Vector2(x, y)); } } for (int x = 1; x < 4; x++) { for (int y = 1; y < 4; y++) { positionList.Remove(new Vector2(x, y)); } } //创建主角 if (GameManager.Instance.isFirstStart) { GameManager.Instance.isFirstStart = false; GameObject p = GameObject.Instantiate(player, new Vector2(1, 1), Quaternion.identity); GameManager.Instance.player = p; // p.transform.SetParent(mapholder); // player.GetComponent<playInfo>().RoleType = (RoleType)PlayerPrefs.GetInt("roleType", 0); } //创建围墙 SpawnWall(new Vector2(Random.Range(xLength / 5, xLength / 2), 0), 0); SpawnWall(new Vector2(Random.Range(xLength / 5, xLength / 2), yLength - 1), 0); SpawnWall(new Vector2(0, Random.Range(yLength / 5, yLength / 2)), 0); SpawnWall(new Vector2(xLength - 1, Random.Range(yLength / 5, yLength / 2)), 0); SpawnWall(new Vector2(Random.Range(xLength / 2, xLength - 1), yLength - 1), 0); SpawnWall(new Vector2(Random.Range(xLength / 2, xLength - 1), 0), 0); //创建障碍物 int barrierCount = Random.Range(minBarrierCount, maxBarrierCount + 1); for (int i = 0; i < barrierCount; i++) { CreateItemWithoutDoor(barrier, minBarrierCount, maxBarrierCount); } //创建宝箱 int chestCount = Random.Range(minChestCount, maxChestCount + 1); for (int i = 0; i < chestCount; i++) { CreateItemWithoutDoor(medicalChest, minChestCount, maxChestCount); } //创建传送门 Vector2 portalPos = new Vector2(xLength - 2, yLength - 2); GameObject port = GameObject.Instantiate(portal, portalPos, Quaternion.identity); port.transform.SetParent(mapholder); positionList.Remove(portalPos); //创建医疗机器人 if (GameManager.Instance.sceneLevel % 5 == 3) { CreateItemWithoutDoor(medicalRobot, 1, 2); } //创建敌人 int enemyCount = Random.Range(minenemyCount, maxenemyCount + 1); for (int i = 0; i < enemyCount; i++) { int enemy_index = Random.Range(0, 2); CreateItem(enemy[enemy_index], minenemyCount, maxenemyCount); } if (GameManager.Instance.sceneLevel % 5 == 1) { CreateBigItem(enemy[2], 1, 2); } astarPath = GetComponent <AstarPath>(); if (astarPath) { astarPath.Scan(); } }
public IEnumerable<Progress> ScanAsync() { if (this.graphs == null) { yield break; } this.isScanning = true; this.euclideanEmbedding.dirty = false; this.VerifyIntegrity(); this.BlockUntilPathQueueBlocked(); this.pathReturnQueue.ReturnPaths(false); this.BlockUntilPathQueueBlocked(); if (!Application.isPlaying) { GraphModifier.FindAllModifiers(); RelevantGraphSurface.FindAllGraphSurfaces(); } RelevantGraphSurface.UpdateAllPositions(); this.astarData.UpdateShortcuts(); yield return new Progress(0.05f, "Pre processing graphs"); if (AstarPath.OnPreScan != null) { AstarPath.OnPreScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.PreScan); Stopwatch watch = Stopwatch.StartNew(); for (int j = 0; j < this.graphs.Length; j++) { if (this.graphs[j] != null) { this.graphs[j].GetNodes(delegate(GraphNode node) { node.Destroy(); return true; }); } } for (int i = 0; i < this.graphs.Length; i++) { if (this.graphs[i] != null) { float minp = Mathf.Lerp(0.1f, 0.8f, (float)i / (float)this.graphs.Length); float maxp = Mathf.Lerp(0.1f, 0.8f, ((float)i + 0.95f) / (float)this.graphs.Length); string progressDescriptionPrefix = string.Concat(new object[] { "Scanning graph ", i + 1, " of ", this.graphs.Length, " - " }); foreach (Progress progress in this.ScanGraph(this.graphs[i])) { yield return new Progress(Mathf.Lerp(minp, maxp, progress.progress), progressDescriptionPrefix + progress.description); } } } yield return new Progress(0.8f, "Post processing graphs"); if (AstarPath.OnPostScan != null) { AstarPath.OnPostScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.PostScan); try { this.FlushWorkItemsInternal(false); } catch (Exception exception) { UnityEngine.Debug.LogException(exception); } yield return new Progress(0.9f, "Computing areas"); this.FloodFill(); this.VerifyIntegrity(); yield return new Progress(0.95f, "Late post processing"); this.isScanning = false; if (AstarPath.OnLatePostScan != null) { AstarPath.OnLatePostScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.LatePostScan); this.euclideanEmbedding.dirty = true; this.euclideanEmbedding.RecalculatePivots(); this.PerformBlockingActions(true, true); watch.Stop(); this.lastScanTime = (float)watch.Elapsed.TotalSeconds; GC.Collect(); this.Log("Scanning - Process took " + (this.lastScanTime * 1000f).ToString("0") + " ms to complete"); yield break; }
public GraphUpdateProcessor (AstarPath astar) { this.astar = astar; }
public void OnGUI() { if (!this.show || (!Application.isPlaying && !this.showInEditor)) { return; } if (this.style == null) { this.style = new GUIStyle(); this.style.normal.textColor = Color.white; this.style.padding = new RectOffset(5, 5, 5, 5); } if (Time.realtimeSinceStartup - this.lastUpdate > 0.5f || this.cachedText == null || !Application.isPlaying) { this.lastUpdate = Time.realtimeSinceStartup; this.boxRect = new Rect(5f, (float)this.yOffset, 310f, 40f); this.text.set_Length(0); this.text.AppendLine("A* Pathfinding Project Debugger"); this.text.Append("A* Version: ").Append(AstarPath.Version.ToString()); if (this.showMemProfile) { this.boxRect.height = this.boxRect.height + 200f; this.text.AppendLine(); this.text.AppendLine(); this.text.Append("Currently allocated".PadRight(25)); this.text.Append(((float)this.allocMem / 1000000f).ToString("0.0 MB")); this.text.AppendLine(); this.text.Append("Peak allocated".PadRight(25)); this.text.Append(((float)this.peakAlloc / 1000000f).ToString("0.0 MB")).AppendLine(); this.text.Append("Last collect peak".PadRight(25)); this.text.Append(((float)this.collectAlloc / 1000000f).ToString("0.0 MB")).AppendLine(); this.text.Append("Allocation rate".PadRight(25)); this.text.Append(((float)this.allocRate / 1000000f).ToString("0.0 MB")).AppendLine(); this.text.Append("Collection frequency".PadRight(25)); this.text.Append(this.delta.ToString("0.00")); this.text.Append("s\n"); this.text.Append("Last collect fps".PadRight(25)); this.text.Append((1f / this.lastDeltaTime).ToString("0.0 fps")); this.text.Append(" ("); this.text.Append(this.lastDeltaTime.ToString("0.000 s")); this.text.Append(")"); } if (this.showFPS) { this.text.AppendLine(); this.text.AppendLine(); this.text.Append("FPS".PadRight(25)).Append((1f / this.delayedDeltaTime).ToString("0.0 fps")); float num = float.PositiveInfinity; for (int i = 0; i < this.fpsDrops.Length; i++) { if (this.fpsDrops[i] < num) { num = this.fpsDrops[i]; } } this.text.AppendLine(); this.text.Append(("Lowest fps (last " + this.fpsDrops.Length + ")").PadRight(25)).Append(num.ToString("0.0")); } if (this.showPathProfile) { AstarPath active = AstarPath.active; this.text.AppendLine(); if (active == null) { this.text.Append("\nNo AstarPath Object In The Scene"); } else { if (ListPool <Vector3> .GetSize() > this.maxVecPool) { this.maxVecPool = ListPool <Vector3> .GetSize(); } if (ListPool <GraphNode> .GetSize() > this.maxNodePool) { this.maxNodePool = ListPool <GraphNode> .GetSize(); } this.text.Append("\nPool Sizes (size/total created)"); for (int j = 0; j < this.debugTypes.Length; j++) { this.debugTypes[j].Print(this.text); } } } this.cachedText = this.text.ToString(); } if (this.font != null) { this.style.font = this.font; this.style.fontSize = this.fontSize; } this.boxRect.height = this.style.CalcHeight(new GUIContent(this.cachedText), this.boxRect.width); GUI.Box(this.boxRect, string.Empty); GUI.Label(this.boxRect, this.cachedText, this.style); if (this.showGraph) { float num2 = float.PositiveInfinity; float num3 = 0f; float num4 = float.PositiveInfinity; float num5 = 0f; for (int k = 0; k < this.graph.Length; k++) { num2 = Mathf.Min(this.graph[k].memory, num2); num3 = Mathf.Max(this.graph[k].memory, num3); num4 = Mathf.Min(this.graph[k].fps, num4); num5 = Mathf.Max(this.graph[k].fps, num5); } GUI.color = Color.blue; float num6 = (float)Mathf.RoundToInt(num3 / 100000f); GUI.Label(new Rect(5f, (float)Screen.height - AstarMath.MapTo(num2, num3, 0f + this.graphOffset, this.graphHeight + this.graphOffset, num6 * 1000f * 100f) - 10f, 100f, 20f), (num6 / 10f).ToString("0.0 MB")); num6 = Mathf.Round(num2 / 100000f); GUI.Label(new Rect(5f, (float)Screen.height - AstarMath.MapTo(num2, num3, 0f + this.graphOffset, this.graphHeight + this.graphOffset, num6 * 1000f * 100f) - 10f, 100f, 20f), (num6 / 10f).ToString("0.0 MB")); GUI.color = Color.green; num6 = Mathf.Round(num5); GUI.Label(new Rect(55f, (float)Screen.height - AstarMath.MapTo(num4, num5, 0f + this.graphOffset, this.graphHeight + this.graphOffset, num6) - 10f, 100f, 20f), num6.ToString("0 FPS")); num6 = Mathf.Round(num4); GUI.Label(new Rect(55f, (float)Screen.height - AstarMath.MapTo(num4, num5, 0f + this.graphOffset, this.graphHeight + this.graphOffset, num6) - 10f, 100f, 20f), num6.ToString("0 FPS")); } }
/** Makes sure #active is set to this object and that #astarData is not null. * Also calls OnEnable for the #colorSettings and initializes astarData.userConnections if it wasn't initialized before */ public void SetUpReferences () { active = this; if (astarData == null) { astarData = new AstarData (); } if (astarData.userConnections == null) { astarData.userConnections = new UserConnection[0]; } if (colorSettings == null) { colorSettings = new AstarColor (); } colorSettings.OnEnable (); }
/** 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"}; } } }
public IEnumerator DemoConstantPath() { ConstantPath constPath = ConstantPath.Construct(end.position, searchLength, null); AstarPath.StartPath(constPath); lastPath = constPath; // Wait for the path to be calculated yield return(StartCoroutine(constPath.WaitForPath())); ClearPrevious(); // The following code will build a mesh with a square for each node visited List <GraphNode> nodes = constPath.allNodes; Mesh mesh = new Mesh(); List <Vector3> verts = new List <Vector3>(); #if FALSE // Just some debugging code which selects random points on the nodes List <Vector3> pts = Pathfinding.PathUtilities.GetPointsOnNodes(nodes, 20, 0); Vector3 avg = Vector3.zero; for (int i = 0; i < pts.Count; i++) { Debug.DrawRay(pts[i], Vector3.up * 5, Color.red, 3); avg += pts[i]; } if (pts.Count > 0) { avg /= pts.Count; } for (int i = 0; i < pts.Count; i++) { pts[i] -= avg; } Pathfinding.PathUtilities.GetPointsAroundPoint(start.position, AstarPath.active.data.graphs[0] as IRaycastableGraph, pts, 0, 1); for (int i = 0; i < pts.Count; i++) { Debug.DrawRay(pts[i], Vector3.up * 5, Color.blue, 3); } #endif bool drawRaysInstead = false; // This will loop through the nodes from furthest away to nearest, not really necessary... but why not :D for (int i = nodes.Count - 1; i >= 0; i--) { Vector3 pos = (Vector3)nodes[i].position + pathOffset; if (verts.Count == 65000 && !drawRaysInstead) { Debug.LogError("Too many nodes, rendering a mesh would throw 65K vertex error. Using Debug.DrawRay instead for the rest of the nodes"); drawRaysInstead = true; } if (drawRaysInstead) { Debug.DrawRay(pos, Vector3.up, Color.blue); continue; } // Add vertices in a square GridGraph gg = AstarData.GetGraph(nodes[i]) as GridGraph; float scale = 1F; if (gg != null) { scale = gg.nodeSize; } verts.Add(pos + new Vector3(-0.5F, 0, -0.5F) * scale); verts.Add(pos + new Vector3(0.5F, 0, -0.5F) * scale); verts.Add(pos + new Vector3(-0.5F, 0, 0.5F) * scale); verts.Add(pos + new Vector3(0.5F, 0, 0.5F) * scale); } // Build triangles for the squares Vector3[] vs = verts.ToArray(); int[] tris = new int[(3 * vs.Length) / 2]; for (int i = 0, j = 0; i < vs.Length; j += 6, i += 4) { tris[j + 0] = i; tris[j + 1] = i + 1; tris[j + 2] = i + 2; tris[j + 3] = i + 1; tris[j + 4] = i + 3; tris[j + 5] = i + 2; } Vector2[] uv = new Vector2[vs.Length]; // Set up some basic UV for (int i = 0; i < uv.Length; i += 4) { uv[i] = new Vector2(0, 0); uv[i + 1] = new Vector2(1, 0); uv[i + 2] = new Vector2(0, 1); uv[i + 3] = new Vector2(1, 1); } mesh.vertices = vs; mesh.triangles = tris; mesh.uv = uv; mesh.RecalculateNormals(); GameObject go = new GameObject("Mesh", typeof(MeshRenderer), typeof(MeshFilter)); MeshFilter fi = go.GetComponent <MeshFilter>(); fi.mesh = mesh; MeshRenderer re = go.GetComponent <MeshRenderer>(); re.material = squareMat; lastRender.Add(go); }
public void SerializeEditorSettings(NavGraph graph, ISerializableGraphEditor editor, AstarPath active) { if (editor == null) { Debug.LogError ("The editor specified is Null"); return; } //The script will return to this value and write the number of variables serialized with the simple serializer positionAtCounter = (int)writerStream.BaseStream.Position; writerStream.Write (0);//This will be overwritten counter = 0; editor.SerializeSettings (graph,this); }
// Token: 0x06002A44 RID: 10820 RVA: 0x001C7F37 File Offset: 0x001C6137 public IEnumerator DemoConstantPath() { ConstantPath constPath = ConstantPath.Construct(this.end.position, this.searchLength, null); AstarPath.StartPath(constPath, false); this.lastPath = constPath; yield return(base.StartCoroutine(constPath.WaitForPath())); this.ClearPrevious(); List <GraphNode> allNodes = constPath.allNodes; Mesh mesh = new Mesh(); List <Vector3> list = new List <Vector3>(); bool flag = false; for (int i = allNodes.Count - 1; i >= 0; i--) { Vector3 a = (Vector3)allNodes[i].position + this.pathOffset; if (list.Count == 65000 && !flag) { Debug.LogError("Too many nodes, rendering a mesh would throw 65K vertex error. Using Debug.DrawRay instead for the rest of the nodes"); flag = true; } if (flag) { Debug.DrawRay(a, Vector3.up, Color.blue); } else { GridGraph gridGraph = AstarData.GetGraph(allNodes[i]) as GridGraph; float d = 1f; if (gridGraph != null) { d = gridGraph.nodeSize; } list.Add(a + new Vector3(-0.5f, 0f, -0.5f) * d); list.Add(a + new Vector3(0.5f, 0f, -0.5f) * d); list.Add(a + new Vector3(-0.5f, 0f, 0.5f) * d); list.Add(a + new Vector3(0.5f, 0f, 0.5f) * d); } } Vector3[] array = list.ToArray(); int[] array2 = new int[3 * array.Length / 2]; int j = 0; int num = 0; while (j < array.Length) { array2[num] = j; array2[num + 1] = j + 1; array2[num + 2] = j + 2; array2[num + 3] = j + 1; array2[num + 4] = j + 3; array2[num + 5] = j + 2; num += 6; j += 4; } Vector2[] array3 = new Vector2[array.Length]; for (int k = 0; k < array3.Length; k += 4) { array3[k] = new Vector2(0f, 0f); array3[k + 1] = new Vector2(1f, 0f); array3[k + 2] = new Vector2(0f, 1f); array3[k + 3] = new Vector2(1f, 1f); } mesh.vertices = array; mesh.triangles = array2; mesh.uv = array3; mesh.RecalculateNormals(); GameObject gameObject = new GameObject("Mesh", new Type[] { typeof(MeshRenderer), typeof(MeshFilter) }); gameObject.GetComponent <MeshFilter>().mesh = mesh; gameObject.GetComponent <MeshRenderer>().material = this.squareMat; this.lastRender.Add(gameObject); yield break; }
/** Starts a path specified by PathTypesDemo.activeDemo */ void DemoPath() { Path p = null; if (activeDemo == DemoMode.ABPath) { p = ABPath.Construct(start.position, end.position, OnPathComplete); if (agents != null && agents.Length > 0) { List <Vector3> pts = Pathfinding.Util.ListPool <Vector3> .Claim(agents.Length); Vector3 avg = Vector3.zero; for (int i = 0; i < agents.Length; i++) { pts.Add(agents[i].transform.position); avg += pts[i]; } avg /= pts.Count; for (int i = 0; i < agents.Length; i++) { pts[i] -= avg; } Pathfinding.PathUtilities.GetPointsAroundPoint(end.position, AstarPath.active.graphs[0] as IRaycastableGraph, pts, 0, 0.2f); for (int i = 0; i < agents.Length; i++) { if (agents[i] == null) { continue; } agents[i].target.position = pts[i]; agents[i].UpdatePath(); } } } else if (activeDemo == DemoMode.MultiTargetPath) { MultiTargetPath mp = MultiTargetPath.Construct(multipoints.ToArray(), end.position, null, OnPathComplete); p = mp; } else if (activeDemo == DemoMode.RandomPath) { RandomPath rp = RandomPath.Construct(start.position, searchLength, OnPathComplete); rp.spread = spread; rp.aimStrength = aimStrength; rp.aim = end.position; p = rp; } else if (activeDemo == DemoMode.FleePath) { FleePath fp = FleePath.Construct(start.position, end.position, searchLength, OnPathComplete); fp.aimStrength = aimStrength; fp.spread = spread; p = fp; } else if (activeDemo == DemoMode.ConstantPath) { StartCoroutine(CalculateConstantPath()); p = null; } else if (activeDemo == DemoMode.FloodPath) { FloodPath fp = FloodPath.Construct(end.position, null); lastFlood = fp; p = fp; } else if (activeDemo == DemoMode.FloodPathTracer && lastFlood != null) { FloodPathTracer fp = FloodPathTracer.Construct(end.position, lastFlood, OnPathComplete); p = fp; } if (p != null) { AstarPath.StartPath(p); lastPath = p; } }
/** 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); // Trying to prevent simple modding to add support for more than one thread if ( numThreads > 1 ) { threadCount = ThreadCount.One; numThreads = 1; } 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 (); // Flush work items, possibly added in initialize to load graph data FlushWorkItems(); if (scanOnStartup) { if (!astarData.cacheStartup || astarData.data_cachedStartup == null) { Scan (); } } }
protected void Awake() { _pathfinder = FindObjectOfType <AstarPath>(); GameEvents.LayoutChanged += UpdateGraph; }
/** Clears up variables and other stuff, destroys graphs. * Note that when destroying an AstarPath object, all static variables such as callbacks will be cleared. */ public void OnDestroy () { if (logPathResults == PathLog.Heavy) Debug.Log ("+++ AstarPath Component Destroyed - Cleaning Up Pathfinding Data +++"); if ( active != this ) return; //Don't accept any more path calls to this AstarPath instance. //This will cause all eventual multithreading threads to exit pathQueue.TerminateReceivers(); BlockUntilPathQueueBlocked(); FlushWorkItems (); if (logPathResults == PathLog.Heavy) Debug.Log ("Processing Eventual Work Items"); // Process work items until done // Nope, don't do this //PerformBlockingActions (true); //Resume graph update thread, will cause it to terminate graphUpdateAsyncEvent.Set(); //Try to join pathfinding threads if (threads != null) { for (int i=0;i<threads.Length;i++) { #if UNITY_WEBPLAYER if (!threads[i].Join(200)) { Debug.LogError ("Could not terminate pathfinding thread["+i+"] in 200ms." + "Not good.\nUnity webplayer does not support Thread.Abort\nHoping that it will be terminated by Unity WebPlayer"); } #else if (!threads[i].Join (50)) { Debug.LogError ("Could not terminate pathfinding thread["+i+"] in 50ms, trying Thread.Abort"); threads[i].Abort (); } #endif } } if (logPathResults == PathLog.Heavy) Debug.Log ("Returning Paths"); //Return all paths ReturnPaths (false); //Just in case someone happened to request a path in ReturnPath() (even though they should get canceled) pathReturnStack.PopAll (); if (logPathResults == PathLog.Heavy) Debug.Log ("Destroying Graphs"); //Clean graphs up astarData.OnDestroy (); if (logPathResults == PathLog.Heavy) Debug.Log ("Cleaning up variables"); //Clear variables up, static variables are good to clean up, otherwise the next scene might get weird data floodStack = null; graphUpdateQueue = null; //Clear all callbacks OnDrawGizmosCallback = null; OnAwakeSettings = null; OnGraphPreScan = null; OnGraphPostScan = null; OnPathPreSearch = null; OnPathPostSearch = null; OnPreScan = null; OnPostScan = null; OnLatePostScan = null; On65KOverflow = null; OnGraphsUpdated = null; OnSafeCallback = null; OnThreadSafeCallback = null; threads = null; threadInfos = null; PathsCompleted = 0; active = null; }
public MeshNode(AstarPath astar) : base(astar) { }
/** 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; //If updating graphs, graph info might be corrupt right now if (pathQueue != null && pathQueue.AllReceiversBlocked && workItems.Count > 0) 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; GraphNodeDelegateCancelable del = DrawUnwalkableNode; for (int i=0;i<graphs.Length;i++) { if (graphs[i] != null) graphs[i].GetNodes (del); } } if (OnDrawGizmosCallback != null) { OnDrawGizmosCallback (); } AstarProfiler.EndProfile ("OnDrawGizmos"); }
public void OnGUI() { if (!show || (!Application.isPlaying && !showInEditor)) { return; } if (style == null) { style = new GUIStyle(); style.normal.textColor = Color.white; style.padding = new RectOffset(5, 5, 5, 5); } if (Time.realtimeSinceStartup - lastUpdate > 0.5f || cachedText == null || !Application.isPlaying) { lastUpdate = Time.realtimeSinceStartup; boxRect = new Rect(5, yOffset, 310, 40); text.Length = 0; text.AppendLine("A* Pathfinding Project Debugger"); text.Append("A* Version: ").Append(AstarPath.Version.ToString()); if (showMemProfile) { boxRect.height += 200; text.AppendLine(); text.AppendLine(); text.Append("Currently allocated".PadRight(25)); text.Append((allocMem / 1000000F).ToString("0.0 MB")); text.AppendLine(); text.Append("Peak allocated".PadRight(25)); text.Append((peakAlloc / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Last collect peak".PadRight(25)); text.Append((collectAlloc / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Allocation rate".PadRight(25)); text.Append((allocRate / 1000000F).ToString("0.0 MB")).AppendLine(); text.Append("Collection frequency".PadRight(25)); text.Append(delta.ToString("0.00")); text.Append("s\n"); text.Append("Last collect fps".PadRight(25)); text.Append((1F / lastDeltaTime).ToString("0.0 fps")); text.Append(" ("); text.Append(lastDeltaTime.ToString("0.000 s")); text.Append(")"); } if (showFPS) { text.AppendLine(); text.AppendLine(); text.Append("FPS".PadRight(25)).Append((1F / delayedDeltaTime).ToString("0.0 fps")); float minFps = Mathf.Infinity; for (int i = 0; i < fpsDrops.Length; i++) { if (fpsDrops[i] < minFps) { minFps = fpsDrops[i]; } } text.AppendLine(); text.Append(("Lowest fps (last " + fpsDrops.Length + ")").PadRight(25)).Append(minFps.ToString("0.0")); } if (showPathProfile) { AstarPath astar = AstarPath.active; text.AppendLine(); if (astar == null) { text.Append("\nNo AstarPath Object In The Scene"); } else { if (Pathfinding.Util.ListPool <Vector3> .GetSize() > maxVecPool) { maxVecPool = Pathfinding.Util.ListPool <Vector3> .GetSize(); } if (Pathfinding.Util.ListPool <Pathfinding.GraphNode> .GetSize() > maxNodePool) { maxNodePool = Pathfinding.Util.ListPool <Pathfinding.GraphNode> .GetSize(); } text.Append("\nPool Sizes (size/total created)"); for (int i = 0; i < debugTypes.Length; i++) { debugTypes[i].Print(text); } } } cachedText = text.ToString(); } if (font != null) { style.font = font; style.fontSize = fontSize; } boxRect.height = style.CalcHeight(new GUIContent(cachedText), boxRect.width); GUI.Box(boxRect, ""); GUI.Label(boxRect, cachedText, style); if (showGraph) { float minMem = float.PositiveInfinity, maxMem = 0, minFPS = float.PositiveInfinity, maxFPS = 0; for (int i = 0; i < graph.Length; i++) { minMem = Mathf.Min(graph[i].memory, minMem); maxMem = Mathf.Max(graph[i].memory, maxMem); minFPS = Mathf.Min(graph[i].fps, minFPS); maxFPS = Mathf.Max(graph[i].fps, maxFPS); } float line; GUI.color = Color.blue; //Round to nearest x.x MB line = Mathf.RoundToInt(maxMem / (100.0f * 1000)); // *1000*100 GUI.Label(new Rect(5, Screen.height - AstarMath.MapTo(minMem, maxMem, 0 + graphOffset, graphHeight + graphOffset, line * 1000 * 100) - 10, 100, 20), (line / 10.0f).ToString("0.0 MB")); line = Mathf.Round(minMem / (100.0f * 1000)); // *1000*100 GUI.Label(new Rect(5, Screen.height - AstarMath.MapTo(minMem, maxMem, 0 + graphOffset, graphHeight + graphOffset, line * 1000 * 100) - 10, 100, 20), (line / 10.0f).ToString("0.0 MB")); GUI.color = Color.green; //Round to nearest x.x MB line = Mathf.Round(maxFPS); // *1000*100 GUI.Label(new Rect(55, Screen.height - AstarMath.MapTo(minFPS, maxFPS, 0 + graphOffset, graphHeight + graphOffset, line) - 10, 100, 20), (line).ToString("0 FPS")); line = Mathf.Round(minFPS); // *1000*100 GUI.Label(new Rect(55, Screen.height - AstarMath.MapTo(minFPS, maxFPS, 0 + graphOffset, graphHeight + graphOffset, line) - 10, 100, 20), (line).ToString("0 FPS")); } }
/** Serializes the nodes in the graph. * \astarpro */ public void SerializeNodes(NavGraph graph, AstarPath active) { if (mask == SMask.SaveNodes) { ISerializableGraph serializeGraph = graph as ISerializableGraph; if (serializeGraph == null) { Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType()); return; } if (graph.nodes == null || graph.nodes.Length == 0) { writerStream.Write (0); //Debug.LogWarning ("No nodes to serialize"); return; } writerStream.Write (graph.nodes.Length); //writerStream.Write (savingToFile ? 753 : 1337); Debug.Log ("Stored nodes "+" "+writerStream.BaseStream.Position); SizeProfiler.Begin ("Graph specific nodes",writerStream); AddVariableAnchor ("DeserializeGraphNodes"); serializeGraph.SerializeNodes (graph.nodes,this); SizeProfiler.End ("Graph specific nodes",writerStream); AddVariableAnchor ("DeserializeNodes"); if (mask == SMask.RunLengthEncoding) { SizeProfiler.Begin ("RLE Penalty",writerStream); //Penalties int lastValue = (int)graph.nodes[0].penalty; int lastEntry = 0; for (int i=1;i<graph.nodes.Length;i++) { if (graph.nodes[i].penalty != lastValue || (i-lastEntry) >= byte.MaxValue-1) { writerStream.Write ((byte)(i-lastEntry)); writerStream.Write (lastValue); lastValue = (int)graph.nodes[i].penalty; lastEntry = i; } } writerStream.Write ((byte)(graph.nodes.Length-lastEntry)); writerStream.Write (lastValue); SizeProfiler.Begin ("RLE Flags",writerStream); //Flags lastValue = graph.nodes[0].flags; lastEntry = 0; for (int i=1;i<graph.nodes.Length;i++) { if (graph.nodes[i].flags != lastValue || (i-lastEntry) >= byte.MaxValue) { writerStream.Write ((byte)(i-lastEntry)); writerStream.Write (lastValue); lastValue = graph.nodes[i].flags; lastEntry = i; } } writerStream.Write ((byte)(graph.nodes.Length-lastEntry)); writerStream.Write (lastValue); SizeProfiler.End ("RLE Flags",writerStream); } SizeProfiler.Begin ("Nodes, other",writerStream); for (int i=0;i<graph.nodes.Length;i++) { SerializeNode (graph.nodes[i], writerStream); } SizeProfiler.End ("Nodes, other",writerStream); } }
public override void OnInspectorGUI() { GraphUpdateScene script = target as GraphUpdateScene; #if !UNITY_LE_4_3 Undo.RecordObject(script, "modify settings on GraphUpdateObject"); #endif if (script.points == null) { script.points = new Vector3[0]; } if (script.points == null || script.points.Length == 0) { if (script.GetComponent <Collider>() != null) { EditorGUILayout.HelpBox("No points, using collider.bounds", MessageType.Info); } else if (script.GetComponent <Renderer>() != null) { EditorGUILayout.HelpBox("No points, using renderer.bounds", MessageType.Info); } else { EditorGUILayout.HelpBox("No points and no collider or renderer attached, will not affect anything", MessageType.Warning); } } Vector3[] prePoints = script.points; #if UNITY_4 EditorGUILayout.PropertyField(serializedObject.FindProperty("points"), true); #else DrawDefaultInspector(); #endif #if UNITY_LE_4_3 EditorGUI.indentLevel = 1; #else EditorGUI.indentLevel = 0; #endif script.updatePhysics = EditorGUILayout.Toggle(new GUIContent("Update Physics", "Perform similar calculations on the nodes as during scan.\n" + "Grid Graphs will update the position of the nodes and also check walkability using collision.\nSee online documentation for more info."), script.updatePhysics); if (script.updatePhysics) { EditorGUI.indentLevel++; script.resetPenaltyOnPhysics = EditorGUILayout.Toggle(new GUIContent("Reset Penalty On Physics", "Will reset the penalty to the default value during the update."), script.resetPenaltyOnPhysics); EditorGUI.indentLevel--; } script.updateErosion = EditorGUILayout.Toggle(new GUIContent("Update Erosion", "Recalculate erosion for grid graphs.\nSee online documentation for more info"), script.updateErosion); if (prePoints != script.points) { script.RecalcConvex(); HandleUtility.Repaint(); } bool preConvex = script.convex; script.convex = EditorGUILayout.Toggle(new GUIContent("Convex", "Sets if only the convex hull of the points should be used or the whole polygon"), script.convex); if (script.convex != preConvex) { script.RecalcConvex(); HandleUtility.Repaint(); } script.minBoundsHeight = EditorGUILayout.FloatField(new GUIContent("Min Bounds Height", "Defines a minimum height to be used for the bounds of the GUO.\nUseful if you define points in 2D (which would give height 0)"), script.minBoundsHeight); script.applyOnStart = EditorGUILayout.Toggle("Apply On Start", script.applyOnStart); script.applyOnScan = EditorGUILayout.Toggle("Apply On Scan", script.applyOnScan); script.modifyWalkability = EditorGUILayout.Toggle(new GUIContent("Modify walkability", "If true, walkability of all nodes will be modified"), script.modifyWalkability); if (script.modifyWalkability) { EditorGUI.indentLevel++; script.setWalkability = EditorGUILayout.Toggle(new GUIContent("Walkability", "Nodes' walkability will be set to this value"), script.setWalkability); EditorGUI.indentLevel--; } script.penaltyDelta = EditorGUILayout.IntField(new GUIContent("Penalty Delta", "A penalty will be added to the nodes, usually you need very large values, at least 1000-10000.\n" + "A higher penalty will mean that agents will try to avoid those nodes."), script.penaltyDelta); if (script.penaltyDelta < 0) { EditorGUILayout.HelpBox("Be careful when lowering the penalty. Negative penalties are not supported and will instead underflow and get really high.\n" + "You can set an initial penalty on graphs (see their settings) and then lower them like this to get regions which are easier to traverse.", MessageType.Warning); } script.modifyTag = EditorGUILayout.Toggle(new GUIContent("Modify Tags", "Should the tags of the nodes be modified"), script.modifyTag); if (script.modifyTag) { EditorGUI.indentLevel++; script.setTag = EditorGUILayout.Popup("Set Tag", script.setTag, AstarPath.FindTagNames()); EditorGUI.indentLevel--; } if (GUILayout.Button("Tags can be used to restrict which units can walk on what ground. Click here for more info", "HelpBox")) { Application.OpenURL(AstarPathEditor.GetURL("tags")); } EditorGUILayout.Separator(); bool worldSpace = EditorGUILayout.Toggle(new GUIContent("Use World Space", "Specify coordinates in world space or local space. When using local space you can move the GameObject " + "around and the points will follow.\n" + "Some operations, like calculating the convex hull, and snapping to Y will change axis depending on how the object is rotated if world space is not used." ), script.useWorldSpace); if (worldSpace != script.useWorldSpace) { #if !UNITY_LE_4_3 Undo.RecordObject(script, "switch use-world-space"); #endif script.ToggleUseWorldSpace(); } #if UNITY_4 EditorGUI.BeginChangeCheck(); #endif script.lockToY = EditorGUILayout.Toggle("Lock to Y", script.lockToY); if (script.lockToY) { EditorGUI.indentLevel++; script.lockToYValue = EditorGUILayout.FloatField("Lock to Y value", script.lockToYValue); EditorGUI.indentLevel--; #if !UNITY_LE_4_3 if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(script, "change Y locking"); } #endif script.LockToY(); } EditorGUILayout.Separator(); if (GUI.changed) { #if UNITY_LE_4_3 Undo.RegisterUndo(script, "Modify Settings on GraphUpdateObject"); #endif EditorUtility.SetDirty(target); } if (GUILayout.Button("Clear all points")) { #if UNITY_LE_4_3 Undo.RegisterUndo(script, "Removed All Points"); #endif script.points = new Vector3[0]; EditorUtility.SetDirty(target); script.RecalcConvex(); } }
/** Called to serialize a graphs settings. \note Before calling this, setting #sPrefix to something unique for the graph is a good idea to avoid collisions in variable names */ public void SerializeSettings(NavGraph graph, AstarPath active) { ISerializableGraph serializeGraph = graph as ISerializableGraph; if (serializeGraph == null) { Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType()); return; } serializeGraph.SerializeSettings (this); }
/** Called on graph rescanning, updates the current node */ private void OnRescan(AstarPath active) { Teleport(); Debug.LogWarning("On Rescan"); }
public void DeSerializeEditorSettings(NavGraph graph, ISerializableGraphEditor editor, AstarPath active) { if (editor == null) { Debug.LogError ("The editor specified is Null"); return; } editor.DeSerializeSettings (graph,this); }
public static void WaitForPath(Path path) { AstarPath.BlockUntilCalculated(path); }
//This is intended for quick saving of settings for e.g Undo operations public void DeSerializeSettings(NavGraph graph, AstarPath active) { ISerializableGraph serializeGraph = graph as ISerializableGraph; if (serializeGraph == null) { Debug.LogError ("The graph specified is not (de)serializable (how it could be serialized in the first place is a mystery) the graph was of type "+graph.GetType()); return; } graph.open = readerStream.ReadBoolean (); //readerStream.ReadString (); serializeGraph.DeSerializeSettings (this); }
public static void RegisterSafeUpdate(Action callback, bool threadSafe) { AstarPath.RegisterSafeUpdate(callback); }
public PointNode (AstarPath astar) : base (astar) { }
// Token: 0x06000045 RID: 69 RVA: 0x00002D7F File Offset: 0x00000F7F public IEnumerable <Progress> ScanAsync(NavGraph[] graphsToScan = null) { if (graphsToScan == null) { graphsToScan = this.graphs; } if (graphsToScan == null) { yield break; } if (this.isScanning) { throw new InvalidOperationException("Another async scan is already running"); } this.isScanning = true; this.VerifyIntegrity(); PathProcessor.GraphUpdateLock graphUpdateLock = this.PausePathfinding(); this.pathReturnQueue.ReturnPaths(false); if (!Application.isPlaying) { this.data.FindGraphTypes(); GraphModifier.FindAllModifiers(); } yield return(new Progress(0.05f, "Pre processing graphs")); if (AstarPath.OnPreScan != null) { AstarPath.OnPreScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.PreScan); this.data.LockGraphStructure(false); Stopwatch watch = Stopwatch.StartNew(); for (int j = 0; j < graphsToScan.Length; j++) { if (graphsToScan[j] != null) { ((IGraphInternals)graphsToScan[j]).DestroyAllNodes(); } } int num; for (int i = 0; i < graphsToScan.Length; i = num + 1) { if (graphsToScan[i] != null) { float minp = Mathf.Lerp(0.1f, 0.8f, (float)i / (float)graphsToScan.Length); float maxp = Mathf.Lerp(0.1f, 0.8f, ((float)i + 0.95f) / (float)graphsToScan.Length); string progressDescriptionPrefix = string.Concat(new object[] { "Scanning graph ", i + 1, " of ", graphsToScan.Length, " - " }); IEnumerator <Progress> coroutine = this.ScanGraph(graphsToScan[i]).GetEnumerator(); for (;;) { try { if (!coroutine.MoveNext()) { break; } } catch { this.isScanning = false; this.data.UnlockGraphStructure(); graphUpdateLock.Release(); throw; } Progress progress = coroutine.Current; yield return(progress.MapTo(minp, maxp, progressDescriptionPrefix)); } progressDescriptionPrefix = null; coroutine = null; } num = i; } this.data.UnlockGraphStructure(); yield return(new Progress(0.8f, "Post processing graphs")); if (AstarPath.OnPostScan != null) { AstarPath.OnPostScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.PostScan); this.FlushWorkItems(); yield return(new Progress(0.9f, "Computing areas")); this.FloodFill(); yield return(new Progress(0.95f, "Late post processing")); this.isScanning = false; if (AstarPath.OnLatePostScan != null) { AstarPath.OnLatePostScan(this); } GraphModifier.TriggerEvent(GraphModifier.EventType.LatePostScan); this.euclideanEmbedding.dirty = true; this.euclideanEmbedding.RecalculatePivots(); this.FlushWorkItems(); graphUpdateLock.Release(); watch.Stop(); this.lastScanTime = (float)watch.Elapsed.TotalSeconds; GC.Collect(); if (this.logPathResults != PathLog.None && this.logPathResults != PathLog.OnlyErrors) { UnityEngine.Debug.Log("Scanning - Process took " + (this.lastScanTime * 1000f).ToString("0") + " ms to complete"); } yield break; }