/// <summary> /// copy from AstarPathEditor, because can't access Editor code here /// </summary> public static void MenuScan() { if (AstarPath.active == null) { AstarPath.active = FindObjectOfType(typeof(AstarPath)) as AstarPath; if (AstarPath.active == null) { return; } } if (!Application.isPlaying && (AstarPath.active.astarData.graphs == null || AstarPath.active.astarData.graphTypes == null)) { UnityEditor.EditorUtility.DisplayProgressBar("Scanning", "Deserializing", 0); AstarPath.active.astarData.DeserializeGraphs(); } UnityEditor.EditorUtility.DisplayProgressBar("Scanning", "Scanning...", 0); try { OnScanStatus info = progress => UnityEditor.EditorUtility.DisplayProgressBar("Scanning", progress.description, progress.progress); AstarPath.active.ScanLoop(info); } catch (System.Exception e) { EB.Debug.LogError("There was an error generating the graphs:\n" + e + "\n\nIf you think this is a bug, please contact me on arongranberg.com (post a comment)\n"); UnityEditor.EditorUtility.DisplayDialog("Error Generating Graphs", "There was an error when generating graphs, check the console for more info", "Ok"); throw e; } finally { UnityEditor.EditorUtility.ClearProgressBar(); } }
protected void ScanTiledNavmesh(OnScanStatus statusCallback) { #if BNICKSON_UPDATED if (generateFromInputMesh) { AStarPathfindingWalkableArea[] walkAreas = GameObject.FindObjectsOfType(typeof(AStarPathfindingWalkableArea)) as AStarPathfindingWalkableArea[]; if (isSingleInputMesh) { if (1 == walkAreas.Length) { GenerateTileFromInputMesh(walkAreas[0]); } } else { GenerateTilesForZones(walkAreas); } } else { ScanAllTiles(statusCallback); } #else ScanAllTiles(statusCallback); #endif }
public void ScanLoop(OnScanStatus statusCallback) { foreach (Progress progress in this.ScanAsync(null)) { statusCallback(progress); } }
public override void ScanInternal(OnScanStatus statusCallback) { if (this.sourceMesh == null) { return; } this.GenerateMatrix(); Vector3[] vertices = this.sourceMesh.vertices; this.triangles = this.sourceMesh.triangles; TriangleMeshNode.SetNavmeshHolder(this.active.astarData.GetGraphIndex(this), this); this.GenerateNodes(vertices, this.triangles, out this.originalVertices, out this._vertices); }
public void ScanInternal(OnScanStatus statusCallback) { if (sourceMesh == null) { return; } GenerateMatrix(); Vector3[] vectorVertices = sourceMesh.vertices; triangles = sourceMesh.triangles; TriangleMeshNode.SetNavmeshHolder(active.astarData.GetGraphIndex(this), this); GenerateNodes(vectorVertices, triangles, out originalVertices, out _vertices); }
public override void ScanInternal(OnScanStatus statusCallback) { // Create a matrix which just moves the nodes and scales their positions by #scale // The SetMatrix call will save it to a variable called just "matrix" SetMatrix(Matrix4x4.TRS(bottomLeftCorner, Quaternion.identity, Vector3.one * scale)); // Create an array containing all nodes nodes = CreateNodes(); // Now all nodes are created, let's create some connections between them! for (int i = 0; i < nodes.GetLength(0); i++) { for (int j = 0; j < nodes.GetLength(1); j++) { SetUpNodeConnections(i, j); } } }
public override void ScanInternal(OnScanStatus statusCallback) { if (sourceMesh == null) { return; } GenerateMatrix(); //float startTime = 0;//Time.realtimeSinceStartup; var vectorVertices = sourceMesh.vertices; triangles = sourceMesh.triangles; TriangleMeshNode.SetNavmeshHolder(active.astarData.GetGraphIndex(this), this); GenerateNodes(vectorVertices, triangles, out originalVertices, out _vertices); }
public override void ScanInternal(OnScanStatus statusCallback) { this.Width = 1 << this.editorWidthLog2; this.Height = 1 << this.editorHeightLog2; this.map = new BitArray(this.Width * this.Height); for (int i = 0; i < this.Width; i++) { for (int j = 0; j < this.Height; j++) { this.map.Set(i + j * this.Width, this.CheckCollision(i, j)); } } QuadtreeNodeHolder holder = new QuadtreeNodeHolder(); this.CreateNodeRec(holder, 0, 0, 0); this.root = holder; this.RecalculateConnectionsRec(this.root, 0, 0, 0); }
public void ScanInternal (OnScanStatus statusCallback) { Width = 1 << editorWidthLog2; Height = 1 << editorHeightLog2; /** \todo Check if can clear */ map = new BitArray(Width*Height); for (int x=0;x<Width;x++) { for (int y=0;y<Height;y++) { map.Set(x+y*Width, CheckCollision (x,y)); } } var h = new QuadtreeNodeHolder(); CreateNodeRec (h, 0, 0,0); root = h; RecalculateConnectionsRec (root, 0,0,0); }
public void ScanInternal(OnScanStatus statusCallback) { Width = 1 << editorWidthLog2; Height = 1 << editorHeightLog2; /** \todo Check if can clear */ map = new BitArray(Width * Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { map.Set(x + y * Width, CheckCollision(x, y)); } } var h = new QuadtreeNodeHolder(); CreateNodeRec(h, 0, 0, 0); root = h; RecalculateConnectionsRec(root, 0, 0, 0); }
/// <summary> /// Scans the graph, called from <see cref="AstarPath.ScanInternal"/> /// Override this function to implement custom scanning logic /// The statusCallback may be optionally called to show progress info in the editor /// </summary> public abstract void ScanInternal (OnScanStatus statusCallback);
public override void ScanInternal (OnScanStatus statusCallback) { if (sourceMesh == null) { return; } GenerateMatrix (); //float startTime = 0;//Time.realtimeSinceStartup; Vector3[] vectorVertices = sourceMesh.vertices; triangles = sourceMesh.triangles; TriangleMeshNode.SetNavmeshHolder (active.astarData.GetGraphIndex(this),this); GenerateNodes (vectorVertices,triangles, out originalVertices, out _vertices); }
public override void ScanInternal (OnScanStatus statusCallback) { AstarPath.OnPostScan += new OnScanDelegate(OnPostScan); if (nodeSize <= 0) { return; } // Make sure the matrix is up to date GenerateMatrix(); if (width > 1024 || depth > 1024) { Debug.LogError("One of the grid's sides is longer than 1024 nodes"); return; } SetUpOffsetsAndCosts(); // Get the graph index of this graph int graphIndex = AstarPath.active.astarData.GetGraphIndex(this); // Set a global reference to this graph so that nodes can find it GridNode.SetGridGraph(graphIndex, this); // Create all nodes nodes = new GridNode[width*depth]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new GridNode(active); nodes[i].GraphIndex = (uint)graphIndex; } // Create and initialize the collision class if (collision == null) { collision = new GraphCollision(); } collision.Initialize(matrix, nodeSize); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { var node = nodes[z*width+x]; node.NodeInGridIndex = z*width+x; // Updates the position of the node // and a bunch of other things UpdateNodePositionCollision(node, x, z); } } for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { var node = nodes[z*width + x]; // Recalculate connections to other nodes CalculateConnections(x, z, node); } } // Apply erosion ErodeWalkableArea(); }
protected void ScanAllTiles (OnScanStatus statusCallback) { #if ASTARDEBUG Console.WriteLine ("Recast Graph -- Collecting Meshes"); #endif AstarProfiler.StartProfile ("Finding Meshes"); List<ExtraMesh> extraMeshes; System.Console.WriteLine ("Collecting Meshes"); CollectMeshes (out extraMeshes, forcedBounds); AstarProfiler.EndProfile ("Finding Meshes"); //---- //Voxel grid size int gw = (int)(forcedBounds.size.x/cellSize + 0.5f); int gd = (int)(forcedBounds.size.z/cellSize + 0.5f); if (!useTiles) { tileSizeX = gw; tileSizeZ = gd; } else { tileSizeX = editorTileSize; tileSizeZ = editorTileSize; } //Number of tiles int tw = (gw + tileSizeX-1) / tileSizeX; int td = (gd + tileSizeZ-1) / tileSizeZ; tileXCount = tw; tileZCount = td; if (tileXCount * tileZCount > TileIndexMask+1) { throw new System.Exception ("Too many tiles ("+(tileXCount * tileZCount)+") maximum is "+(TileIndexMask+1)+ "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector."); } tiles = new NavmeshTile[tileXCount*tileZCount]; #if ASTARDEBUG Console.WriteLine ("Recast Graph -- Creating Voxel Base"); #endif //Create the voxelizer and set all settings Voxelize vox = new Voxelize (cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope); vox.inputExtraMeshes = extraMeshes; vox.maxEdgeLength = maxEdgeLength; int lastUp = -1; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); //Generate all tiles for (int z=0;z<td;z++) { for (int x=0;x<tw;x++) { int tileNum = z*tileXCount + x; System.Console.WriteLine ("Generating Tile #"+(tileNum) + " of " + td*tw); //Call statusCallback only 10 times since it is very slow in the editor if ((tileNum*10/tiles.Length > lastUp || watch.ElapsedMilliseconds > 2000) && statusCallback != null) { lastUp = tileNum*10/tiles.Length; watch.Reset(); watch.Start(); statusCallback (new Progress (AstarMath.MapToRange (0.1f, 0.9f, tileNum/(float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length)); } BuildTileMesh (vox, x,z); } } System.Console.WriteLine ("Assigning Graph Indices"); if (statusCallback != null) statusCallback (new Progress (0.9f, "Connecting tiles")); //Assign graph index to nodes uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex (this); GraphNodeDelegateCancelable del = delegate (GraphNode n) { n.GraphIndex = graphIndex; return true; }; GetNodes (del); for (int z=0;z<td;z++) { for (int x=0;x<tw;x++) { System.Console.WriteLine ("Connecing Tile #"+(z*tileXCount + x) + " of " + td*tw); if (x < tw-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x+1 + z*tileXCount]); if (z < td-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x + (z+1)*tileXCount]); } } AstarProfiler.PrintResults (); }
protected void ScanTiledNavmesh (OnScanStatus statusCallback) { ScanAllTiles (statusCallback); }
public override void ScanInternal (OnScanStatus statusCallback) { if (nodeSize <= 0) { return; } GenerateMatrix (); if (width > 1024 || depth > 1024) { Debug.LogError ("One of the grid's sides is longer than 1024 nodes"); return; } lastScannedWidth = width; lastScannedDepth = depth; SetUpOffsetsAndCosts (); LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this); maxClimb = Mathf.Clamp (maxClimb,0,characterHeight); var linkedCells = new LinkedLevelCell[width*depth]; collision = collision ?? new GraphCollision (); collision.Initialize (matrix,nodeSize); for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { linkedCells[z*width+x] = new LinkedLevelCell (); LinkedLevelCell llc = linkedCells[z*width+x]; Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); RaycastHit[] hits = collision.CheckHeightAll (pos); for (int i=0;i<hits.Length/2;i++) { RaycastHit tmp = hits[i]; hits[i] = hits[hits.Length-1-i]; hits[hits.Length-1-i] = tmp; } if (hits.Length > 0) { LinkedLevelNode lln = null; for (int i=0;i<hits.Length;i++) { var tmp = new LinkedLevelNode (); tmp.position = hits[i].point; if (lln != null) { /** \todo Use hit.distance instead */ if (tmp.position.y - lln.position.y <= mergeSpanRange) { lln.position = tmp.position; lln.hit = hits[i]; lln.walkable = collision.Check (tmp.position); continue; } } tmp.walkable = collision.Check (tmp.position); tmp.hit = hits[i]; tmp.height = float.PositiveInfinity; if (llc.first == null) { llc.first = tmp; lln = tmp; } else { lln.next = tmp; lln.height = tmp.position.y - lln.position.y; lln = lln.next; } } } else { var lln = new LinkedLevelNode (); lln.position = pos; lln.height = float.PositiveInfinity; lln.walkable = !collision.unwalkableWhenNoGround; llc.first = lln; } } } int spanCount = 0; layerCount = 0; // Count the total number of nodes in the graph for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { LinkedLevelCell llc = linkedCells[z*width+x]; LinkedLevelNode lln = llc.first; int cellCount = 0; // Loop through all nodes in this cell do { cellCount++; spanCount++; lln = lln.next; } while (lln != null); layerCount = cellCount > layerCount ? cellCount : layerCount; } } if (layerCount > LevelGridNode.MaxLayerCount) { Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")"); return; } // Create all nodes nodes = new LevelGridNode[width*depth*layerCount]; for (int i=0;i<nodes.Length;i++) { nodes[i] = new LevelGridNode (active); nodes[i].Penalty = initialPenalty; } int nodeIndex = 0; // Max slope in cosinus float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { LinkedLevelCell llc = linkedCells[z*width+x]; LinkedLevelNode lln = llc.first; llc.index = nodeIndex; int count = 0; int layerIndex = 0; do { var node = nodes[z*width+x + width*depth*layerIndex]; #if ASTAR_SET_LEVELGRIDNODE_HEIGHT node.height = lln.height; #endif node.SetPosition ((Int3)lln.position); node.Walkable = lln.walkable; // Adjust penalty based on the surface slope if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) { //Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle) float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up); // Add penalty based on normal if (penaltyAngle) { node.Penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor); } // Check if the slope is flat enough to stand on if (angle < cosAngle) { node.Walkable = false; } } node.NodeInGridIndex = z*width+x; if (lln.height < characterHeight) { node.Walkable = false; } node.WalkableErosion = node.Walkable; nodeIndex++; count++; lln = lln.next; layerIndex++; } while (lln != null); for (;layerIndex<layerCount;layerIndex++) { nodes[z*width+x + width*depth*layerIndex] = null; } llc.count = count; } } nodeIndex = 0; nodeCellIndices = new int[linkedCells.Length]; for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { for (int i=0;i<layerCount;i++) { GraphNode node = nodes[z*width+x + width*depth*i]; CalculateConnections (nodes,node,x,z,i); } } } uint graphIndex = (uint)active.astarData.GetGraphIndex(this); for (int i=0;i<nodes.Length;i++) { var lgn = nodes[i]; if (lgn == null) continue; UpdatePenalty (lgn); lgn.GraphIndex = graphIndex; // Set the node to be unwalkable if it hasn't got any connections if (!lgn.HasAnyGridConnections ()) { lgn.Walkable = false; lgn.WalkableErosion = lgn.Walkable; } } ErodeWalkableArea (); }
protected void ScanAllTiles(OnScanStatus statusCallback) { int num = (int)(this.forcedBounds.size.x / this.cellSize + 0.5f); int num2 = (int)(this.forcedBounds.size.z / this.cellSize + 0.5f); if (!this.useTiles) { this.tileSizeX = num; this.tileSizeZ = num2; } else { this.tileSizeX = this.editorTileSize; this.tileSizeZ = this.editorTileSize; } int num3 = (num + this.tileSizeX - 1) / this.tileSizeX; int num4 = (num2 + this.tileSizeZ - 1) / this.tileSizeZ; this.tileXCount = num3; this.tileZCount = num4; if (this.tileXCount * this.tileZCount > 524288) { throw new Exception(string.Concat(new object[] { "Too many tiles (", this.tileXCount * this.tileZCount, ") maximum is ", 524288, "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector." })); } this.tiles = new RecastGraph.NavmeshTile[this.tileXCount * this.tileZCount]; if (this.scanEmptyGraph) { for (int i = 0; i < num4; i++) { for (int j = 0; j < num3; j++) { this.tiles[i * this.tileXCount + j] = RecastGraph.NewEmptyTile(j, i); } } return; } Console.WriteLine("Collecting Meshes"); List<ExtraMesh> inputExtraMeshes; this.CollectMeshes(out inputExtraMeshes, this.forcedBounds); this.walkableClimb = Mathf.Min(this.walkableClimb, this.walkableHeight); Voxelize voxelize = new Voxelize(this.cellHeight, this.cellSize, this.walkableClimb, this.walkableHeight, this.maxSlope); voxelize.inputExtraMeshes = inputExtraMeshes; voxelize.maxEdgeLength = this.maxEdgeLength; int num5 = -1; Stopwatch stopwatch = Stopwatch.StartNew(); for (int k = 0; k < num4; k++) { for (int l = 0; l < num3; l++) { int num6 = k * this.tileXCount + l; Console.WriteLine(string.Concat(new object[] { "Generating Tile #", num6, " of ", num4 * num3 })); if (statusCallback != null && (num6 * 10 / this.tiles.Length > num5 || stopwatch.ElapsedMilliseconds > 2000L)) { num5 = num6 * 10 / this.tiles.Length; stopwatch.Reset(); stopwatch.Start(); statusCallback(new Progress(AstarMath.MapToRange(0.1f, 0.9f, (float)num6 / (float)this.tiles.Length), string.Concat(new object[] { "Building Tile ", num6, "/", this.tiles.Length }))); } this.BuildTileMesh(voxelize, l, k); } } Console.WriteLine("Assigning Graph Indices"); if (statusCallback != null) { statusCallback(new Progress(0.9f, "Connecting tiles")); } uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex(this); GraphNodeDelegateCancelable del = delegate(GraphNode n) { n.GraphIndex = graphIndex; return true; }; this.GetNodes(del); for (int m = 0; m < num4; m++) { for (int n2 = 0; n2 < num3; n2++) { Console.WriteLine(string.Concat(new object[] { "Connecing Tile #", m * this.tileXCount + n2, " of ", num4 * num3 })); if (n2 < num3 - 1) { this.ConnectTiles(this.tiles[n2 + m * this.tileXCount], this.tiles[n2 + 1 + m * this.tileXCount]); } if (m < num4 - 1) { this.ConnectTiles(this.tiles[n2 + m * this.tileXCount], this.tiles[n2 + (m + 1) * this.tileXCount]); } } } }
// Token: 0x06000526 RID: 1318 RVA: 0x0002CF88 File Offset: 0x0002B388 public override void ScanInternal(OnScanStatus statusCallback) { if (this.root == null) { GameObject[] array = GameObject.FindGameObjectsWithTag(this.searchTag); if (array == null) { this.nodes = new PointNode[0]; this.nodeCount = 0; return; } this.nodes = new PointNode[array.Length]; this.nodeCount = this.nodes.Length; for (int i = 0; i < this.nodes.Length; i++) { this.nodes[i] = new PointNode(this.active); } for (int j = 0; j < array.Length; j++) { this.nodes[j].SetPosition((Int3)array[j].transform.position); this.nodes[j].Walkable = true; this.nodes[j].gameObject = array[j].gameObject; } } else if (!this.recursive) { this.nodes = new PointNode[this.root.childCount]; this.nodeCount = this.nodes.Length; for (int k = 0; k < this.nodes.Length; k++) { this.nodes[k] = new PointNode(this.active); } int num = 0; IEnumerator enumerator = this.root.GetEnumerator(); try { while (enumerator.MoveNext()) { object obj = enumerator.Current; Transform transform = (Transform)obj; this.nodes[num].SetPosition((Int3)transform.position); this.nodes[num].Walkable = true; this.nodes[num].gameObject = transform.gameObject; num++; } } finally { IDisposable disposable; if ((disposable = (enumerator as IDisposable)) != null) { disposable.Dispose(); } } } else { this.nodes = new PointNode[PointGraph.CountChildren(this.root)]; this.nodeCount = this.nodes.Length; for (int l = 0; l < this.nodes.Length; l++) { this.nodes[l] = new PointNode(this.active); } int num2 = 0; this.AddChildren(ref num2, this.root); } if (this.optimizeForSparseGraph) { this.RebuildNodeLookup(); } if (this.maxDistance >= 0f) { List <PointNode> list = new List <PointNode>(3); List <uint> list2 = new List <uint>(3); for (int m = 0; m < this.nodes.Length; m++) { list.Clear(); list2.Clear(); PointNode pointNode = this.nodes[m]; if (this.optimizeForSparseGraph) { Int3 lhs = this.WorldToLookupSpace(pointNode.position); int num3 = (this.lookupCellSize.y != 0) ? PointGraph.ThreeDNeighbours.Length : 9; for (int n = 0; n < num3; n++) { Int3 key = lhs + PointGraph.ThreeDNeighbours[n]; PointNode next; if (this.nodeLookup.TryGetValue(key, out next)) { while (next != null) { float num4 = 0f; if (this.IsValidConnection(pointNode, next, out num4)) { list.Add(next); list2.Add((uint)Mathf.RoundToInt(num4 * 1000f)); } next = next.next; } } } } else { for (int num5 = 0; num5 < this.nodes.Length; num5++) { if (m != num5) { PointNode pointNode2 = this.nodes[num5]; float num6 = 0f; if (this.IsValidConnection(pointNode, pointNode2, out num6)) { list.Add(pointNode2); list2.Add((uint)Mathf.RoundToInt(num6 * 1000f)); } } } } pointNode.connections = list.ToArray(); pointNode.connectionCosts = list2.ToArray(); } } }
public override void ScanInternal (OnScanStatus statusCallback) { AstarPath.OnPostScan += new OnScanDelegate (OnPostScan); scans++; if (nodeSize <= 0) { return; } GenerateMatrix (); if (width > 1024 || depth > 1024) { Debug.LogError ("One of the grid's sides is longer than 1024 nodes"); return; } #if !ASTAR_JPS if (this.useJumpPointSearch) { Debug.LogError ("Trying to use Jump Point Search, but support for it is not enabled. Please enable it in the inspector (Grid Graph settings)."); } #endif SetUpOffsetsAndCosts (); int graphIndex = AstarPath.active.astarData.GetGraphIndex(this); GridNode.SetGridGraph (graphIndex,this); nodes = new GridNode[width*depth]; for (int i=0;i<nodes.Length;i++) { nodes[i] = new GridNode(active); nodes[i].GraphIndex = (uint)graphIndex; } if (collision == null) { collision = new GraphCollision (); } collision.Initialize (matrix,nodeSize); textureData.Initialize (); for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x]; node.NodeInGridIndex = z*width+x; UpdateNodePositionCollision (node,x,z); textureData.Apply (node,x,z); } } for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x]; CalculateConnections (nodes,x,z,node); #if ASTARDEBUG if (z == 5 && x == 5) { int index = z*width+x; Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white); } #endif } } ErodeWalkableArea (); }
public override void ScanInternal (OnScanStatus statusCallback) { AstarPath.OnPostScan += new OnScanDelegate (OnPostScan); scans++; if (nodeSize <= 0) { return; } GenerateMatrix (); if (width > 1024 || depth > 1024) { Debug.LogError ("One of the grid's sides is longer than 1024 nodes"); return; } //GenerateBounds (); /*neighbourOffsets = new int[8] { -width-1,-width,-width+1, -1,1, width-1,width,width+1 }*/ SetUpOffsetsAndCosts (); //GridNode.RemoveGridGraph (this); int graphIndex = AstarPath.active.astarData.GetGraphIndex(this); GridNode.SetGridGraph (graphIndex,this); //graphNodes = new GridNode[width*depth]; //nodes = CreateNodes (width*depth); nodes = new GridNode[width*depth]; for (int i=0;i<nodes.Length;i++) { nodes[i] = new GridNode(active); nodes[i].GraphIndex = (uint)graphIndex; } if (collision == null) { collision = new GraphCollision (); } collision.Initialize (matrix,nodeSize); textureData.Initialize (); //Max slope in cosinus //float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad); for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x];//new GridNode (); node.NodeInGridIndex = z*width+x; UpdateNodePositionCollision (node,x,z); textureData.Apply (node,x,z); /*node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); RaycastHit hit; bool walkable = true; node.position = collision.CheckHeight (node.position, out hit, out walkable); node.penalty = 0;//Mathf.RoundToInt (Random.value*100); //Check if the node is on a slope steeper than permitted if (walkable && useRaycastNormal && collision.heightCheck) { if (hit.normal != Vector3.zero) { //Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle) float angle = Vector3.Dot (hit.normal.normalized,Vector3.up); if (angle < cosAngle) { walkable = false; } } } //If the walkable flag has already been set to false, there is no point in checking for it again if (walkable) { node.walkable = collision.Check (node.position); } else { node.walkable = walkable; }*/ } } for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x]; CalculateConnections (nodes,x,z,node); #if ASTARDEBUG if (z == 5 && x == 5) { int index = z*width+x; Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black); Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white); } #endif } } ErodeWalkableArea (); //Assign the nodes to the main storage //startIndex = AstarPath.active.AssignNodes (graphNodes); //endIndex = startIndex+graphNodes.Length; }
public override void ScanInternal(OnScanStatus statusCallback) { var walkableOpenSpaceWaypoints = GenerateWalkableOpenSpaceWaypoints(); var walkableSystemWaypoints = GenerateWalkableInteriorSystemWaypoints(); int nextNodeIndex = Constants.Zero; AddNodes(walkableOpenSpaceWaypoints, Topography.OpenSpace.AStarTagValue(), ref nextNodeIndex); // OpenSpaceTagMask AddNodes(walkableSystemWaypoints, Topography.System.AStarTagValue(), ref nextNodeIndex); // SystemTagMask MakeConnections(); }
public override void ScanInternal (OnScanStatus status) { scans++; if (nodeSize <= 0) { return; } GenerateMatrix (); if (width > 1024 || depth > 1024) { Debug.LogError ("One of the grid's sides is longer than 1024 nodes"); return; } //GenerateBounds (); /*neighbourOffsets = new int[8] { -width-1,-width,-width+1, -1,1, width-1,width,width+1 }*/ SetUpOffsetsAndCosts (); //GridNode.RemoveGridGraph (this); LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this); //graphNodes = new LevelGridNode[width*depth]; //nodes = CreateNodes (width*depth); //graphNodes = nodes as LevelGridNode[]; maxClimb = Mathf.Clamp (maxClimb,0,characterHeight); LinkedLevelCell[] linkedCells = new LinkedLevelCell[width*depth]; if (collision == null) { collision = new GraphCollision (); } collision.Initialize (matrix,nodeSize); for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { linkedCells[z*width+x] = new LinkedLevelCell (); LinkedLevelCell llc = linkedCells[z*width+x]; //GridNode node = graphNodes[z*width+x];//new LevelGridNode (); //node.SetIndex (z*width+x); Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); RaycastHit[] hits = collision.CheckHeightAll (pos); //Sort the hits based on distance with bubble sort (fast enough) //Furthest away first (i.e lowest nodes in the graph) /*bool changed = true; while (changed) { changed = false; for (int i=0;i<hits.Length-1;i++) { if (hits[i].distance < hits[i+1].distance) { RaycastHit tmp = hits[i]; hits[i] = hits[i+1]; hits[i+1] = tmp; changed = true; } } }*/ for (int i=0;i<hits.Length/2;i++) { RaycastHit tmp = hits[i]; hits[i] = hits[hits.Length-1-i]; hits[hits.Length-1-i] = tmp; } if (hits.Length > 0) { //lln.position = hits[0].point; //lln.walkable = collision.Check (lln.position); /*LinkedLevelNode lln = new LinkedLevelNode (); lln.position = hits[0].point; lln.walkable = collision.Check (lln.position); llc.first = lln;*/ LinkedLevelNode lln = null; for (int i=0;i<hits.Length;i++) { LinkedLevelNode tmp = new LinkedLevelNode (); tmp.position = hits[i].point; if (lln != null) { /** \todo Use hit.distance instead */ if (tmp.position.y - lln.position.y <= mergeSpanRange) { //if (tmp.position.y > lln.position.y) { lln.position = tmp.position; lln.hit = hits[i]; lln.walkable = collision.Check (tmp.position); //} continue; } } tmp.walkable = collision.Check (tmp.position); tmp.hit = hits[i]; tmp.height = float.PositiveInfinity; if (llc.first == null) { llc.first = tmp; lln = tmp; } else { lln.next = tmp; lln.height = tmp.position.y - lln.position.y; lln = lln.next; } } } else { LinkedLevelNode lln = new LinkedLevelNode (); lln.position = pos; lln.height = float.PositiveInfinity; lln.walkable = !collision.unwalkableWhenNoGround; llc.first = lln; } //node.penalty = 0;//Mathf.RoundToInt (Random.value*100); //node.walkable = collision.Check (node.position); //node.SetGridIndex (gridIndex); } } int spanCount = 0; layerCount = 0; //Count the total number of nodes in the graph for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { LinkedLevelCell llc = linkedCells[z*width+x]; LinkedLevelNode lln = llc.first; int cellCount = 0; //Loop through all nodes in this cell do { cellCount++; spanCount++; lln = lln.next; } while (lln != null); layerCount = cellCount > layerCount ? cellCount : layerCount; } } if (layerCount > LevelGridNode.MaxLayerCount) { Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")"); return; } //Create all nodes nodes = new LevelGridNode[width*depth*layerCount]; for (int i=0;i<nodes.Length;i++) { nodes[i] = new LevelGridNode (active); nodes[i].Penalty = initialPenalty; } int nodeIndex = 0; //Max slope in cosinus float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { LinkedLevelCell llc = linkedCells[z*width+x]; LinkedLevelNode lln = llc.first; llc.index = nodeIndex; int count = 0; int layerIndex = 0; do { LevelGridNode node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode; #if ASTAR_SET_LEVELGRIDNODE_HEIGHT node.height = lln.height; #endif node.SetPosition ((Int3)lln.position); node.Walkable = lln.walkable; //Adjust penalty based on the surface slope if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) { //Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle) float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up); //Add penalty based on normal if (penaltyAngle) { node.Penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor); } //Check if the slope is flat enough to stand on if (angle < cosAngle) { node.Walkable = false; } } node.NodeInGridIndex = z*width+x; //node.nodeOffset = count; if (lln.height < characterHeight) { node.Walkable = false; } node.WalkableErosion = node.Walkable; nodeIndex++; count++; lln = lln.next; layerIndex++; } while (lln != null); for (;layerIndex<layerCount;layerIndex++) { nodes[z*width+x + width*depth*layerIndex] = null; } llc.count = count; } } nodeIndex = 0; nodeCellIndices = new int[linkedCells.Length]; for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { /*LinkedLevelCell llc = linkedCells[z*width+x]; LinkedLevelNode lln = llc.first; nodeCellIndices[z*width+x] = llc.index; do { LevelGridNode node = (LevelGridNode)nodes[nodeIndex]; CalculateConnections (nodes,linkedCells,node,x,z,n); nodeIndex++; lln = lln.next; } while (lln != null);*/ for (int i=0;i<layerCount;i++) { GraphNode node = nodes[z*width+x + width*depth*i]; CalculateConnections (nodes,node,x,z,i); } } } uint graphIndex = (uint)active.astarData.GetGraphIndex(this); for (int i=0;i<nodes.Length;i++) { LevelGridNode lgn = nodes[i] as LevelGridNode; if (lgn == null) continue; UpdatePenalty (lgn); lgn.GraphIndex = graphIndex; //Set the node to be unwalkable if it hasn't got any connections if (!lgn.HasAnyGridConnections ()) { lgn.Walkable = false; lgn.WalkableErosion = lgn.Walkable; } } /*GridNode node = graphNodes[z*width+x]; CalculateConnections (graphNodes,x,z,node); if (z == 5 && x == 5) { int index = z*width+x; Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black); Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white); }*/ //} //} ErodeWalkableArea (0,0,width,depth); }
public override void ScanInternal(OnScanStatus statusCallback) { if (root == null) { //If there is no root object, try to find nodes with the specified tag instead GameObject[] gos = GameObject.FindGameObjectsWithTag(searchTag); nodeGameObjects = gos; if (gos == null) { nodes = new PointNode[0]; nodeCount = 0; return; } //Create and set up the found nodes nodes = new PointNode[gos.Length]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } //CreateNodes (gos.Length); for (int i = 0; i < gos.Length; i++) { (nodes[i] as PointNode).SetPosition((Int3)gos[i].transform.position); nodes[i].Walkable = true; #if !AstarRelease && FALSE NodeObject nobj = gos[i].GetComponent <NodeObject>(); if (nobj != null) { nodes[i].Walkable = nobj.walkable; } #endif } } else { //Search the root for children and create nodes for them if (!recursive) { nodes = new PointNode[root.childCount]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } nodeGameObjects = new GameObject[nodes.Length]; int c = 0; foreach (Transform child in root) { (nodes[c] as PointNode).SetPosition((Int3)child.position); nodes[c].Walkable = true; nodeGameObjects[c] = child.gameObject; #if !AstarRelease && FALSE NodeObject nobj = child.GetComponent <NodeObject>(); if (nobj != null) { nodes[c].Walkable = nobj.walkable; } #endif c++; } } else { nodes = new PointNode[CountChildren(root)]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } //CreateNodes (CountChildren (root)); nodeGameObjects = new GameObject[nodes.Length]; int startID = 0; AddChildren(ref startID, root); } } if (optimizeForSparseGraph) { RebuildNodeLookup(); } if (maxDistance >= 0) { //To avoid too many allocations, these lists are reused for each node List <PointNode> connections = new List <PointNode>(3); List <uint> costs = new List <uint>(3); //Loop through all nodes and add connections to other nodes for (int i = 0; i < nodes.Length; i++) { connections.Clear(); costs.Clear(); PointNode node = nodes[i]; if (optimizeForSparseGraph) { Int3 p = WorldToLookupSpace(node.position); int l = lookupCellSize.y == 0 ? 9 : ThreeDNeighbours.Length; for (int j = 0; j < l; j++) { Int3 np = p + ThreeDNeighbours[j]; PointNode other; if (nodeLookup.TryGetValue(np, out other)) { while (other != null) { float dist = 0; if (IsValidConnection(node, other, out dist)) { connections.Add(other); /** \todo Is this equal to .costMagnitude */ costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision)); } other = other.next; } } } } else { // Only brute force is available in the free version for (int j = 0; j < nodes.Length; j++) { if (i == j) { continue; } PointNode other = nodes[j]; float dist = 0; if (IsValidConnection(node, other, out dist)) { connections.Add(other); /** \todo Is this equal to .costMagnitude */ costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision)); } } } node.connections = connections.ToArray(); node.connectionCosts = costs.ToArray(); } } //GC can clear this up now. nodeGameObjects = null; }
public override void ScanInternal(OnScanStatus status) { this.scans++; if (this.nodeSize <= 0f) { return; } base.GenerateMatrix(); if (this.width > 1024 || this.depth > 1024) { Debug.LogError("One of the grid's sides is longer than 1024 nodes"); return; } this.lastScannedWidth = this.width; this.lastScannedDepth = this.depth; this.SetUpOffsetsAndCosts(); LevelGridNode.SetGridGraph(this.active.astarData.GetGraphIndex(this), this); this.maxClimb = Mathf.Clamp(this.maxClimb, 0f, this.characterHeight); LinkedLevelCell[] array = new LinkedLevelCell[this.width * this.depth]; if (this.collision == null) { this.collision = new GraphCollision(); } this.collision.Initialize(this.matrix, this.nodeSize); for (int i = 0; i < this.depth; i++) { for (int j = 0; j < this.width; j++) { array[i * this.width + j] = new LinkedLevelCell(); LinkedLevelCell linkedLevelCell = array[i * this.width + j]; Vector3 position = this.matrix.MultiplyPoint3x4(new Vector3((float)j + 0.5f, 0f, (float)i + 0.5f)); RaycastHit[] array2 = this.collision.CheckHeightAll(position); for (int k = 0; k < array2.Length / 2; k++) { RaycastHit raycastHit = array2[k]; array2[k] = array2[array2.Length - 1 - k]; array2[array2.Length - 1 - k] = raycastHit; } if (array2.Length > 0) { LinkedLevelNode linkedLevelNode = null; for (int l = 0; l < array2.Length; l++) { LinkedLevelNode linkedLevelNode2 = new LinkedLevelNode(); linkedLevelNode2.position = array2[l].point; if (linkedLevelNode != null && linkedLevelNode2.position.y - linkedLevelNode.position.y <= this.mergeSpanRange) { linkedLevelNode.position = linkedLevelNode2.position; linkedLevelNode.hit = array2[l]; linkedLevelNode.walkable = this.collision.Check(linkedLevelNode2.position); } else { linkedLevelNode2.walkable = this.collision.Check(linkedLevelNode2.position); linkedLevelNode2.hit = array2[l]; linkedLevelNode2.height = float.PositiveInfinity; if (linkedLevelCell.first == null) { linkedLevelCell.first = linkedLevelNode2; linkedLevelNode = linkedLevelNode2; } else { linkedLevelNode.next = linkedLevelNode2; linkedLevelNode.height = linkedLevelNode2.position.y - linkedLevelNode.position.y; linkedLevelNode = linkedLevelNode.next; } } } } else { linkedLevelCell.first = new LinkedLevelNode { position = position, height = float.PositiveInfinity, walkable = !this.collision.unwalkableWhenNoGround }; } } } int num = 0; this.layerCount = 0; for (int m = 0; m < this.depth; m++) { for (int n = 0; n < this.width; n++) { LinkedLevelCell linkedLevelCell2 = array[m * this.width + n]; LinkedLevelNode linkedLevelNode3 = linkedLevelCell2.first; int num2 = 0; do { num2++; num++; linkedLevelNode3 = linkedLevelNode3.next; }while (linkedLevelNode3 != null); this.layerCount = ((num2 <= this.layerCount) ? this.layerCount : num2); } } if (this.layerCount > 255) { Debug.LogError("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found " + this.layerCount + ")"); return; } this.nodes = new LevelGridNode[this.width * this.depth * this.layerCount]; for (int num3 = 0; num3 < this.nodes.Length; num3++) { this.nodes[num3] = new LevelGridNode(this.active); this.nodes[num3].Penalty = this.initialPenalty; } int num4 = 0; float num5 = Mathf.Cos(this.maxSlope * 0.0174532924f); for (int num6 = 0; num6 < this.depth; num6++) { for (int num7 = 0; num7 < this.width; num7++) { LinkedLevelCell linkedLevelCell3 = array[num6 * this.width + num7]; LinkedLevelNode linkedLevelNode4 = linkedLevelCell3.first; linkedLevelCell3.index = num4; int num8 = 0; int num9 = 0; do { LevelGridNode levelGridNode = this.nodes[num6 * this.width + num7 + this.width * this.depth * num9]; levelGridNode.SetPosition((Int3)linkedLevelNode4.position); levelGridNode.Walkable = linkedLevelNode4.walkable; if (linkedLevelNode4.hit.normal != Vector3.zero && (this.penaltyAngle || num5 < 1f)) { float num10 = Vector3.Dot(linkedLevelNode4.hit.normal.normalized, this.collision.up); if (this.penaltyAngle) { levelGridNode.Penalty += (uint)Mathf.RoundToInt((1f - num10) * this.penaltyAngleFactor); } if (num10 < num5) { levelGridNode.Walkable = false; } } levelGridNode.NodeInGridIndex = num6 * this.width + num7; if (linkedLevelNode4.height < this.characterHeight) { levelGridNode.Walkable = false; } levelGridNode.WalkableErosion = levelGridNode.Walkable; num4++; num8++; linkedLevelNode4 = linkedLevelNode4.next; num9++; }while (linkedLevelNode4 != null); while (num9 < this.layerCount) { this.nodes[num6 * this.width + num7 + this.width * this.depth * num9] = null; num9++; } linkedLevelCell3.count = num8; } } this.nodeCellIndices = new int[array.Length]; for (int num11 = 0; num11 < this.depth; num11++) { for (int num12 = 0; num12 < this.width; num12++) { for (int num13 = 0; num13 < this.layerCount; num13++) { GraphNode node = this.nodes[num11 * this.width + num12 + this.width * this.depth * num13]; this.CalculateConnections(this.nodes, node, num12, num11, num13); } } } uint graphIndex = (uint)this.active.astarData.GetGraphIndex(this); for (int num14 = 0; num14 < this.nodes.Length; num14++) { LevelGridNode levelGridNode2 = this.nodes[num14]; if (levelGridNode2 != null) { this.UpdatePenalty(levelGridNode2); levelGridNode2.GraphIndex = graphIndex; if (!levelGridNode2.HasAnyGridConnections()) { levelGridNode2.Walkable = false; levelGridNode2.WalkableErosion = levelGridNode2.Walkable; } } } this.ErodeWalkableArea(0, 0, this.width, this.depth); }
public override void ScanInternal(OnScanStatus statusCallback) { TriangleMeshNode.SetNavmeshHolder(AstarPath.active.astarData.GetGraphIndex(this), this); this.ScanTiledNavmesh(statusCallback); }
public override void ScanInternal(OnScanStatus statusCallback) { if (root == null) { //If there is no root object, try to find nodes with the specified tag instead GameObject[] gos = searchTag != null?GameObject.FindGameObjectsWithTag(searchTag) : null; if (gos == null) { nodes = new PointNode[0]; nodeCount = 0; return; } //Create and set up the found nodes nodes = new PointNode[gos.Length]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } for (int i = 0; i < gos.Length; i++) { nodes[i].SetPosition((Int3)gos[i].transform.position); nodes[i].Walkable = true; nodes[i].gameObject = gos[i].gameObject; } } else { //Search the root for children and create nodes for them if (!recursive) { nodes = new PointNode[root.childCount]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } int c = 0; foreach (Transform child in root) { nodes[c].SetPosition((Int3)child.position); nodes[c].Walkable = true; nodes[c].gameObject = child.gameObject; c++; } } else { nodes = new PointNode[CountChildren(root)]; nodeCount = nodes.Length; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new PointNode(active); } //CreateNodes (CountChildren (root)); int startID = 0; AddChildren(ref startID, root); } } if (maxDistance >= 0) { //To avoid too many allocations, these lists are reused for each node var connections = new List <PointNode>(3); var costs = new List <uint>(3); //Loop through all nodes and add connections to other nodes for (int i = 0; i < nodes.Length; i++) { connections.Clear(); costs.Clear(); PointNode node = nodes[i]; // Only brute force is available in the free version for (int j = 0; j < nodes.Length; j++) { if (i == j) { continue; } PointNode other = nodes[j]; float dist; if (IsValidConnection(node, other, out dist)) { connections.Add(other); /** \todo Is this equal to .costMagnitude */ costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision)); } } node.connections = connections.ToArray(); node.connectionCosts = costs.ToArray(); } } }
public override void ScanInternal (OnScanStatus statusCallback) { AstarProfiler.Reset (); AstarProfiler.StartProfile ("Base Scan"); //AstarProfiler.InitializeFastProfile (new string[] {"Rasterize", "Rasterize Inner 1", "Rasterize Inner 2", "Rasterize Inner 3"}); TriangleMeshNode.SetNavmeshHolder (AstarPath.active.astarData.GetGraphIndex (this), this); ScanTiledNavmesh (statusCallback); #if DEBUG_REPLAY DebugReplay.WriteToFile (); #endif AstarProfiler.PrintFastResults(); }
// Scan() has been deprecated, replaced by ScanInternal. public override void ScanInternal(OnScanStatus statusCallback) { // ******************************************************************** // NOTE: removed all code that derived nodes from GameObjects and Tags // ******************************************************************** //D.Log("ScanInternal called."); var walkableOpenSpaceWaypoints = GetWalkableOpenSpaceWaypoints(); var unwalkableOpenSpaceWaypoints = GetUnWalkableOpenSpaceWaypoints(); var walkableSystemWaypoints = GetWalkableInteriorSystemWaypoints(); int waypointCount = walkableOpenSpaceWaypoints.Count + unwalkableOpenSpaceWaypoints.Count + walkableSystemWaypoints.Count; // Make the Nodes array nodes = new PointNode[waypointCount]; nodeCount = waypointCount; //for (int nodeIndex = 0; nodeIndex < waypointCount; nodeIndex++) { // nodes[nodeIndex] = new PointNode(active); //} int nextNodeIndex = Constants.Zero; bool isWalkable = true; PopulateNodes(walkableOpenSpaceWaypoints, openSpaceTagMask, isWalkable, ref nextNodeIndex); //D.Log("NextNodeIndex = {0}.", nextNodeIndex); PopulateNodes(walkableSystemWaypoints, systemTagMask, isWalkable, ref nextNodeIndex); //D.Log("NextNodeIndex = {0}.", nextNodeIndex); isWalkable = false; PopulateNodes(unwalkableOpenSpaceWaypoints, openSpaceTagMask, isWalkable, ref nextNodeIndex); //D.Log("NextNodeIndex = {0}.", nextNodeIndex); D.Log("{0} Pathfinding nodes.", nodeCount); if (maxDistance >= 0) { //To avoid too many allocations, these lists are reused for each node List<PointNode> connections = new List<PointNode>(3); List<uint> costs = new List<uint>(3); //Loop through all nodes and add connections to other nodes int connectionCount = 0; int invalidConnectionCount = 0; for (int i = 0; i < nodes.Length; i++) { connections.Clear(); costs.Clear(); PointNode node = nodes[i]; // OPTIMIZE Only brute force is available in the free version for (int j = 0; j < nodes.Length; j++) { if (i == j) { continue; } PointNode other = nodes[j]; float dist = 0; if (IsValidConnection(node, other, out dist)) { connections.Add(other); /** \todo Is this equal to .costMagnitude */ costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision)); } else { invalidConnectionCount++; } //else if (dist <= maxDistance) { // maxDistance is currently 700 // invalidConnectionCount++; // D.Warn("Connection from Node at {0} to Node at {1} is invalid.", (Vector3)node.position, (Vector3)other.position); // D.AssertException(false); //} } node.connections = connections.ToArray(); connectionCount += connections.Count; node.connectionCosts = costs.ToArray(); } int totalConnectionsAttempted = connectionCount + invalidConnectionCount; D.Log("{0}/{1} valid connections.", connectionCount, totalConnectionsAttempted); } }
protected void ScanAllTiles(OnScanStatus statusCallback) { #if ASTARDEBUG System.Console.WriteLine("Recast Graph -- Collecting Meshes"); #endif #if BNICKSON_UPDATED editorTileSize = (int)(EditorVars.GridSize / cellSize); #endif //---- //Voxel grid size int gw = (int)(forcedBounds.size.x / cellSize + 0.5f); int gd = (int)(forcedBounds.size.z / cellSize + 0.5f); if (!useTiles) { tileSizeX = gw; tileSizeZ = gd; } else { tileSizeX = editorTileSize; tileSizeZ = editorTileSize; } //Number of tiles int tw = (gw + tileSizeX - 1) / tileSizeX; int td = (gd + tileSizeZ - 1) / tileSizeZ; tileXCount = tw; tileZCount = td; if (tileXCount * tileZCount > TileIndexMask + 1) { throw new System.Exception("Too many tiles (" + (tileXCount * tileZCount) + ") maximum is " + (TileIndexMask + 1) + "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector."); } tiles = new NavmeshTile[tileXCount * tileZCount]; #if ASTARDEBUG System.Console.WriteLine("Recast Graph -- Creating Voxel Base"); #endif // If this is true, just fill the graph with empty tiles if (scanEmptyGraph) { for (int z = 0; z < td; z++) { for (int x = 0; x < tw; x++) { tiles[z * tileXCount + x] = NewEmptyTile(x, z); } } return; } AstarProfiler.StartProfile("Finding Meshes"); List <ExtraMesh> extraMeshes; #if !NETFX_CORE || UNITY_EDITOR System.Console.WriteLine("Collecting Meshes"); #endif CollectMeshes(out extraMeshes, forcedBounds); AstarProfiler.EndProfile("Finding Meshes"); // A walkableClimb higher than walkableHeight can cause issues when generating the navmesh since then it can in some cases // Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with navmesh without links) // The editor scripts also enforce this but we enforce it here too just to be sure walkableClimb = Mathf.Min(walkableClimb, walkableHeight); //Create the voxelizer and set all settings var vox = new Voxelize(cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope); vox.inputExtraMeshes = extraMeshes; vox.maxEdgeLength = maxEdgeLength; int lastInfoCallback = -1; var watch = System.Diagnostics.Stopwatch.StartNew(); //Generate all tiles for (int z = 0; z < td; z++) { for (int x = 0; x < tw; x++) { int tileNum = z * tileXCount + x; #if !NETFX_CORE || UNITY_EDITOR System.Console.WriteLine("Generating Tile #" + (tileNum) + " of " + td * tw); #endif //Call statusCallback only 10 times since it is very slow in the editor if (statusCallback != null && (tileNum * 10 / tiles.Length > lastInfoCallback || watch.ElapsedMilliseconds > 2000)) { lastInfoCallback = tileNum * 10 / tiles.Length; watch.Reset(); watch.Start(); statusCallback(new Progress(Mathf.Lerp(0.1f, 0.9f, tileNum / (float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length)); } BuildTileMesh(vox, x, z); } } #if !NETFX_CORE System.Console.WriteLine("Assigning Graph Indices"); #endif if (statusCallback != null) { statusCallback(new Progress(0.9f, "Connecting tiles")); } //Assign graph index to nodes uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex(this); GraphNodeDelegateCancelable del = delegate(GraphNode n) { n.GraphIndex = graphIndex; return(true); }; GetNodes(del); #if BNICKSON_UPDATED #if DEBUG if (useCenterTileOnly && (3 != tileXCount || 3 != tileZCount)) { EB.Debug.LogError("RecastGenerator.ScanAllTiles() : Incorrect amount of tiles generated if ceneter tile is all that is required"); } #endif int centerXTile = (tileXCount / 2); int centerZTile = (tileZCount / 2); #endif for (int z = 0; z < td; z++) { for (int x = 0; x < tw; x++) { #if BNICKSON_UPDATED // if we're only using the center tile, and this is not the center tile if (useCenterTileOnly && !(centerZTile == z && centerXTile == x)) { continue; } #endif #if !NETFX_CORE System.Console.WriteLine("Connecing Tile #" + (z * tileXCount + x) + " of " + td * tw); #endif if (x < tw - 1) { ConnectTiles(tiles[x + z * tileXCount], tiles[x + 1 + z * tileXCount]); } if (z < td - 1) { ConnectTiles(tiles[x + z * tileXCount], tiles[x + (z + 1) * tileXCount]); } } } AstarProfiler.PrintResults(); }
/** Scans all graphs. This is a IEnumerable, you can loop through it to get the progress * \code foreach (Progress progress in AstarPath.active.ScanLoop ()) { * Debug.Log ("Scanning... " + progress.description + " - " + (progress.progress*100).ToString ("0") + "%"); * } \endcode * \see Scan */ public void ScanLoop (OnScanStatus statusCallback) { if (graphs == null) { return; } isScanning = true; VerifyIntegrity (); BlockUntilPathQueueBlocked (); if (!Application.isPlaying) { GraphModifier.FindAllModifiers (); RelevantGraphSurface.FindAllGraphSurfaces (); } RelevantGraphSurface.UpdateAllPositions (); astarData.UpdateShortcuts (); //statusCallback (new Progress (0.02F,"Updating graph shortcuts")); if (statusCallback != null) statusCallback (new Progress (0.05F,"Pre processing graphs")); if (OnPreScan != null) { OnPreScan (this); } GraphModifier.TriggerEvent (GraphModifier.EventType.PreScan); //float startTime = Time.realtimeSinceStartup; System.DateTime startTime = System.DateTime.UtcNow; // Destroy previous nodes for (int i=0;i<graphs.Length;i++) { if (graphs[i] != null) { graphs[i].GetNodes (delegate (GraphNode node) { node.Destroy (); return true; }); } } for (int i=0;i<graphs.Length;i++) { NavGraph graph = graphs[i]; if (graph == null) { if (statusCallback != null) statusCallback (new Progress (AstarMath.MapTo (0.05F,0.7F,(float)(i+0.5F)/(graphs.Length+1)),"Skipping graph "+(i+1)+" of "+graphs.Length+" because it is null")); continue; } if (OnGraphPreScan != null) { if (statusCallback != null) statusCallback (new Progress (AstarMath.MapToRange (0.1F,0.7F,(float)(i)/(graphs.Length)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Pre processing")); OnGraphPreScan (graph); } float minp = AstarMath.MapToRange (0.1F,0.7F,(float)(i)/(graphs.Length)); float maxp = AstarMath.MapToRange (0.1F,0.7F,(float)(i+0.95F)/(graphs.Length)); if (statusCallback != null) statusCallback (new Progress (minp,"Scanning graph "+(i+1)+" of "+graphs.Length)); OnScanStatus info = null; if (statusCallback != null) { info = delegate (Progress p) { p.progress = AstarMath.MapToRange (minp, maxp, p.progress); statusCallback (p); }; } graph.ScanInternal (info); //statusCallback (new Progress (Mathfx.MapTo (0.05F,0.7F,(float)(i+1.9F)/(graphs.Length+1)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Assigning graph indices")); graph.GetNodes (delegate (GraphNode node) { node.GraphIndex = (uint)i; return true; }); if (OnGraphPostScan != null) { if (statusCallback != null) statusCallback (new Progress (AstarMath.MapToRange (0.1F,0.7F,(float)(i+0.95F)/(graphs.Length)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Post processing")); OnGraphPostScan (graph); } } if (statusCallback != null) statusCallback (new Progress (0.8F,"Post processing graphs")); if (OnPostScan != null) { OnPostScan (this); } GraphModifier.TriggerEvent (GraphModifier.EventType.PostScan); ApplyLinks (); //statusCallback (new Progress (0.85F,"Applying links")); try { FlushWorkItems(); } catch (System.Exception e) { Debug.LogException (e); } isScanning = false; if (statusCallback != null) statusCallback (new Progress (0.90F,"Computing areas")); FloodFill (); //statusCallback (new Progress (0.92F,"Updating misc. data")); VerifyIntegrity (); if (statusCallback != null) statusCallback (new Progress (0.95F,"Late post processing")); if (OnLatePostScan != null) { OnLatePostScan (this); } GraphModifier.TriggerEvent (GraphModifier.EventType.LatePostScan); //Perform any blocking actions and unblock (probably, some tasks might take a few frames) PerformBlockingActions(true); lastScanTime = (float)(System.DateTime.UtcNow-startTime).TotalSeconds;//Time.realtimeSinceStartup-startTime; System.GC.Collect (); AstarLog ("Scanning - Process took "+(lastScanTime*1000).ToString ("0")+" ms to complete"); }
public override void ScanInternal (OnScanStatus statusCallback) { AstarPath.OnPostScan += new OnScanDelegate (OnPostScan); scans++; if (nodeSize <= 0) { return; } GenerateMatrix (); if (width > 1024 || depth > 1024) { Debug.LogError ("One of the grid's sides is longer than 1024 nodes"); return; } SetUpOffsetsAndCosts (); int graphIndex = AstarPath.active.astarData.GetGraphIndex(this); GridNode.SetGridGraph (graphIndex,this); nodes = new GridNode[width*depth]; for (int i=0;i<nodes.Length;i++) { nodes[i] = new GridNode(active); nodes[i].GraphIndex = (uint)graphIndex; } if (collision == null) { collision = new GraphCollision (); } collision.Initialize (matrix,nodeSize); for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x]; node.NodeInGridIndex = z*width+x; UpdateNodePositionCollision (node,x,z); } } for (int z = 0; z < depth; z ++) { for (int x = 0; x < width; x++) { GridNode node = nodes[z*width+x]; CalculateConnections (nodes,x,z,node); } } ErodeWalkableArea (); }
/// <summary> /// Scans the graph, called from <see cref="AstarPath.ScanInternal"/> /// Override this function to implement custom scanning logic /// The statusCallback may be optionally called to show progress info in the editor /// </summary> public abstract void ScanInternal(OnScanStatus statusCallback);
protected void ScanAllTiles (OnScanStatus statusCallback) { #if ASTARDEBUG System.Console.WriteLine ("Recast Graph -- Collecting Meshes"); #endif //---- //Voxel grid size int gw = (int)(forcedBounds.size.x/cellSize + 0.5f); int gd = (int)(forcedBounds.size.z/cellSize + 0.5f); if (!useTiles) { tileSizeX = gw; tileSizeZ = gd; } else { tileSizeX = editorTileSize; tileSizeZ = editorTileSize; } //Number of tiles int tw = (gw + tileSizeX-1) / tileSizeX; int td = (gd + tileSizeZ-1) / tileSizeZ; tileXCount = tw; tileZCount = td; if (tileXCount * tileZCount > TileIndexMask+1) { throw new System.Exception ("Too many tiles ("+(tileXCount * tileZCount)+") maximum is "+(TileIndexMask+1)+ "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector."); } tiles = new NavmeshTile[tileXCount*tileZCount]; #if ASTARDEBUG System.Console.WriteLine ("Recast Graph -- Creating Voxel Base"); #endif // If this is true, just fill the graph with empty tiles if ( scanEmptyGraph ) { for (int z=0;z<td;z++) { for (int x=0;x<tw;x++) { tiles[z*tileXCount + x] = NewEmptyTile(x,z); } } return; } AstarProfiler.StartProfile ("Finding Meshes"); List<ExtraMesh> extraMeshes; #if !NETFX_CORE || UNITY_EDITOR System.Console.WriteLine ("Collecting Meshes"); #endif CollectMeshes (out extraMeshes, forcedBounds); AstarProfiler.EndProfile ("Finding Meshes"); // A walkableClimb higher than walkableHeight can cause issues when generating the navmesh since then it can in some cases // Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with navmesh without links) // The editor scripts also enforce this but we enforce it here too just to be sure walkableClimb = Mathf.Min (walkableClimb, walkableHeight); //Create the voxelizer and set all settings var vox = new Voxelize (cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope); vox.inputExtraMeshes = extraMeshes; vox.maxEdgeLength = maxEdgeLength; int lastInfoCallback = -1; var watch = System.Diagnostics.Stopwatch.StartNew(); //Generate all tiles for (int z=0;z<td;z++) { for (int x=0;x<tw;x++) { int tileNum = z*tileXCount + x; #if !NETFX_CORE || UNITY_EDITOR System.Console.WriteLine ("Generating Tile #"+(tileNum) + " of " + td*tw); #endif //Call statusCallback only 10 times since it is very slow in the editor if (statusCallback != null && (tileNum*10/tiles.Length > lastInfoCallback || watch.ElapsedMilliseconds > 2000)) { lastInfoCallback = tileNum*10/tiles.Length; watch.Reset(); watch.Start(); statusCallback (new Progress (AstarMath.MapToRange (0.1f, 0.9f, tileNum/(float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length)); } BuildTileMesh (vox, x,z); } } #if !NETFX_CORE System.Console.WriteLine ("Assigning Graph Indices"); #endif if (statusCallback != null) statusCallback (new Progress (0.9f, "Connecting tiles")); //Assign graph index to nodes uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex (this); GraphNodeDelegateCancelable del = delegate (GraphNode n) { n.GraphIndex = graphIndex; return true; }; GetNodes (del); for (int z=0;z<td;z++) { for (int x=0;x<tw;x++) { #if !NETFX_CORE System.Console.WriteLine ("Connecing Tile #"+(z*tileXCount + x) + " of " + td*tw); #endif if (x < tw-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x+1 + z*tileXCount]); if (z < td-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x + (z+1)*tileXCount]); } } AstarProfiler.PrintResults (); }