public override void GetNodes (GraphNodeDelegateCancelable del) { if (nodes == null) return; for (int i=0;i < nodes.Length;i++) { if (nodes[i] != null && !del(nodes[i])) break; } }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (this.root != null) { this.root.GetNodes(del); } }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (root == null) { return; } root.GetNodes(del); }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (this.nodes != null) { for (int i = 0; (i < this.nodeCount) && del(this.nodes[i]); i++) { } } }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (nodes == null) { return; } for (int i = 0; i < nodes.Length && del(nodes[i]); i++) { } }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (nodes == null) { return; } for (var i = 0; i < nodeCount && del(nodes[i]); i++) { } }
//#endif /** Count nodes in the graph. * Note that this is, unless the graph type has overriden it, an O(n) operation. * * \todo GridGraph should override this */ public virtual int CountNodes() { var count = 0; GraphNodeDelegateCancelable del = delegate(GraphNode node) { count++; return(true); }; GetNodes(del); return(count); }
/** Count nodes in the graph. * Note that this is, unless the graph type has overriden it, an O(n) operation. * * \todo GridGraph should override this */ public virtual int CountNodes() { int count = 0; GraphNodeDelegateCancelable del = node => { count++; return(true); }; GetNodes(del); return(count); }
private void OnDrawGizmos() { if (this.isScanning) { return; } if (AstarPath.active == null) { AstarPath.active = this; } else if (AstarPath.active != this) { return; } if (this.graphs == null) { return; } if (this.workItems.workItemsInProgress) { return; } if (this.showNavGraphs && !this.manualDebugFloorRoof) { this.RecalculateDebugLimits(); } for (int i = 0; i < this.graphs.Length; i++) { if (this.graphs[i] != null && this.graphs[i].drawGizmos) { this.graphs[i].OnDrawGizmos(this.showNavGraphs); } } if (this.showNavGraphs) { this.euclideanEmbedding.OnDrawGizmos(); if (this.showUnwalkableNodes) { Gizmos.color = AstarColor.UnwalkableNode; GraphNodeDelegateCancelable del = new GraphNodeDelegateCancelable(this.DrawUnwalkableNode); for (int j = 0; j < this.graphs.Length; j++) { if (this.graphs[j] != null && this.graphs[j].drawGizmos) { this.graphs[j].GetNodes(del); } } } } if (this.OnDrawGizmosCallback != null) { this.OnDrawGizmosCallback(); } }
protected void GenerateTileFromInputMesh(AStarPathfindingWalkableArea walkArea) { if (null == walkArea) { EB.Debug.LogWarning("GenerateTileFromInputMesh: walkArea is empty"); return; } Mesh inputMesh = walkArea.gameObject.GetComponent <MeshFilter>().sharedMesh; if (null == inputMesh) { EB.Debug.LogWarning("GenerateTileFromInputMesh: inputMesh is empty"); return; } List <Vector3> allPoints = new List <Vector3>(inputMesh.vertices); Bounds bounds = GameUtils.CalculateBounds(allPoints); forcedBoundsCenter = walkArea.transform.TransformPoint(bounds.center); forcedBoundsSize = bounds.size; // this section changes the size of the bounds and tile, so that we always get one single tile SetUpNavMeshToFitOnOneTile(); CalculateNumberOfTiles(ref tileXCount, ref tileZCount); Debug.Assert(tileXCount == 1 && tileZCount == 1, "Their should be only one tile when using a prebuilt nav mesh"); tiles = new NavmeshTile[tileXCount * tileZCount]; // only one tile // ignore this setting scanEmptyGraph = false; // the Vector3 vertices in the mesh need to be converted to the APP Int3 format Int3[] Int3Verts = new Int3[inputMesh.vertices.Length]; for (int i = 0; i < Int3Verts.Length; ++i) { Vector3 tempVert = inputMesh.vertices[i]; tempVert = walkArea.transform.TransformPoint(tempVert); // get the world space position, rather than local space Int3Verts[i] = (Int3)tempVert; } tiles[0] = CreateTile(inputMesh.triangles, Int3Verts, 0, 0); // our single tile //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); }
// Token: 0x06000549 RID: 1353 RVA: 0x0002E604 File Offset: 0x0002CA04 public void GetNodes(GraphNodeDelegateCancelable del) { if (this.node != null) { del(this.node); return; } this.c0.GetNodes(del); this.c1.GetNodes(del); this.c2.GetNodes(del); this.c3.GetNodes(del); }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (this.nodes == null) { return; } int num = 0; while (num < this.nodes.Length && del(this.nodes[num])) { num++; } }
public void GetNodes(GraphNodeDelegateCancelable del) { if (node != null) { del(node); return; } c0.GetNodes(del); c1.GetNodes(del); c2.GetNodes(del); c3.GetNodes(del); }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (this.nodes == null) { return; } for (int i = 0; i < this.nodes.Length; i++) { if (this.nodes[i] != null && !del(this.nodes[i])) { break; } } }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (nodes == null) { return; } for (int i = 0; i < nodes.GetLength(0); i++) { for (int j = 0; j < nodes.GetLength(1); j++) { // Call the delegate and check if it wants // more nodes or not if (!del(nodes[i, j])) { // If it did not want more nodes // then just return return; } } } }
public void GetNodes (GraphNodeDelegateCancelable del) { if (node != null) { del (node); return; } c0.GetNodes (del); c1.GetNodes (del); c2.GetNodes (del); c3.GetNodes (del); }
public override void GetNodes (GraphNodeDelegateCancelable del) { if (nodes == null) return; for (int i=0;i<nodes.Length && del (nodes[i]);i++) {} }
public override void GetNodes(GraphNodeDelegateCancelable del) { if (this.tiles == null) { return; } for (int i = 0; i < this.tiles.Length; i++) { if (this.tiles[i] != null && this.tiles[i].x + this.tiles[i].z * this.tileXCount == i) { TriangleMeshNode[] nodes = this.tiles[i].nodes; if (nodes != null) { int num = 0; while (num < nodes.Length && del(nodes[num])) { num++; } } } } }
/** This performs a linear search through all polygons returning the closest one. * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node * complying with the NNConstraint. * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool) */ public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { Int3 pos = (Int3)position; float minDist = -1; GraphNode minNode = null; float minConstDist = -1; GraphNode minConstNode = null; float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity; GraphNodeDelegateCancelable del = delegate(GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 closest = node.ClosestPointOnNode(position); float dist = ((Vector3)pos - closest).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { if (!node.ContainsPoint((Int3)position)) { float dist = (node.position - pos).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { int dist = AstarMath.Abs(node.position.y - pos.y); if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } } return(true); }; graph.GetNodes(del); NNInfo nninfo = new NNInfo(minNode); //Find the point closest to the nearest triangle if (nninfo.node != null) { TriangleMeshNode node = nninfo.node as TriangleMeshNode; //minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode(position); nninfo.clampedPosition = clP; } nninfo.constrainedNode = minConstNode; if (nninfo.constrainedNode != null) { TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode; //minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode(position); nninfo.constClampedPosition = clP; } return(nninfo); }
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(); }
public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { Int3 pos = (Int3)position; float minDist = -1f; GraphNode minNode = null; float minConstDist = -1f; GraphNode minConstNode = null; float maxDistSqr = (!constraint.constrainDistance) ? float.PositiveInfinity : AstarPath.active.maxNearestNodeDistanceSqr; GraphNodeDelegateCancelable del = delegate(GraphNode _node) { TriangleMeshNode triangleMeshNode3 = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 b = triangleMeshNode3.ClosestPointOnNode(position); float sqrMagnitude = ((Vector3)pos - b).sqrMagnitude; if (minNode == null || sqrMagnitude < minDist) { minDist = sqrMagnitude; minNode = triangleMeshNode3; } if (sqrMagnitude < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude < minConstDist)) { minConstDist = sqrMagnitude; minConstNode = triangleMeshNode3; } } else if (!triangleMeshNode3.ContainsPoint((Int3)position)) { float sqrMagnitude2 = (triangleMeshNode3.position - pos).sqrMagnitude; if (minNode == null || sqrMagnitude2 < minDist) { minDist = sqrMagnitude2; minNode = triangleMeshNode3; } if (sqrMagnitude2 < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude2 < minConstDist)) { minConstDist = sqrMagnitude2; minConstNode = triangleMeshNode3; } } else { int num = AstarMath.Abs(triangleMeshNode3.position.y - pos.y); if (minNode == null || (float)num < minDist) { minDist = (float)num; minNode = triangleMeshNode3; } if ((float)num < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || (float)num < minConstDist)) { minConstDist = (float)num; minConstNode = triangleMeshNode3; } } return(true); }; graph.GetNodes(del); NNInfo result = new NNInfo(minNode); if (result.node != null) { TriangleMeshNode triangleMeshNode = result.node as TriangleMeshNode; Vector3 clampedPosition = triangleMeshNode.ClosestPointOnNode(position); result.clampedPosition = clampedPosition; } result.constrainedNode = minConstNode; if (result.constrainedNode != null) { TriangleMeshNode triangleMeshNode2 = result.constrainedNode as TriangleMeshNode; Vector3 constClampedPosition = triangleMeshNode2.ClosestPointOnNode(position); result.constClampedPosition = constClampedPosition; } return(result); }
public void GetNodes(GraphNodeDelegateCancelable del) { if (this.nodes == null) { return; } int num = 0; while (num < this.nodes.Length && del(this.nodes[num])) { num++; } }
/** Calls a delegate with all nodes in the graph. * This is the primary way of "looping" through all nodes in a graph. * * This function should not change anything in the graph structure. */ public abstract void GetNodes (GraphNodeDelegateCancelable del);
public override void GetNodes (GraphNodeDelegateCancelable del) { /*if (nodes == null) return; for (int i=0;i<nodes.Length && del (nodes[i]);i++) {}*/ if (tiles == null) return; // for (int i=0;i<tiles.Length;i++) { if (tiles[i] == null || tiles[i].x+tiles[i].z*tileXCount != i) continue; TriangleMeshNode[] nodes = tiles[i].nodes; if (nodes == null) continue; for (int j=0;j<nodes.Length && del (nodes[j]);j++) {} } }
public void FloodFill() { if (astar.astarData.graphs == null) { return; } uint area = 0; lastUniqueAreaIndex = 0; if (floodStack == null) { floodStack = new Stack <GraphNode> (1024); } Stack <GraphNode> stack = floodStack; var graphs = astar.graphs; // Iterate through all nodes in all graphs // and reset their Area field for (int i = 0; i < graphs.Length; i++) { NavGraph graph = graphs[i]; if (graph != null) { graph.GetNodes(node => { node.Area = 0; return(true); }); } } int smallAreasDetected = 0; bool warnAboutAreas = false; List <GraphNode> smallAreaList = Pathfinding.Util.ListPool <GraphNode> .Claim(); for (int i = 0; i < graphs.Length; i++) { NavGraph graph = graphs[i]; if (graph == null) { continue; } GraphNodeDelegateCancelable del = delegate(GraphNode node) { if (node.Walkable && node.Area == 0) { area++; uint thisArea = area; if (area > GraphNode.MaxAreaIndex) { if (smallAreaList.Count > 0) { GraphNode smallOne = smallAreaList[smallAreaList.Count - 1]; thisArea = smallOne.Area; smallAreaList.RemoveAt(smallAreaList.Count - 1); //Flood fill the area again with area ID GraphNode.MaxAreaIndex-1, this identifies a small area stack.Clear(); stack.Push(smallOne); smallOne.Area = GraphNode.MaxAreaIndex; while (stack.Count > 0) { stack.Pop().FloodFill(stack, GraphNode.MaxAreaIndex); } smallAreasDetected++; } else { // Forced to consider this a small area area--; thisArea = area; warnAboutAreas = true; } } stack.Clear(); stack.Push(node); int counter = 1; node.Area = thisArea; while (stack.Count > 0) { counter++; stack.Pop().FloodFill(stack, thisArea); } if (counter < astar.minAreaSize) { smallAreaList.Add(node); } } return(true); }; graph.GetNodes(del); } lastUniqueAreaIndex = area; if (warnAboutAreas) { Debug.LogError("Too many areas - The maximum number of areas is " + GraphNode.MaxAreaIndex + ". Try raising the A* Inspector -> Settings -> Min Area Size value. Enable the optimization ASTAR_MORE_AREAS under the Optimizations tab."); } if (smallAreasDetected > 0) { astar.Log(smallAreasDetected + " small areas were detected (fewer than " + astar.minAreaSize + " nodes)," + "these might have the same IDs as other areas, but it shouldn't affect pathfinding in any significant way (you might get All Nodes Searched as a reason for path failure)." + "\nWhich areas are defined as 'small' is controlled by the 'Min Area Size' variable, it can be changed in the A* inspector-->Settings-->Min Area Size" + "\nThe small areas will use the area id " + GraphNode.MaxAreaIndex); } Pathfinding.Util.ListPool <GraphNode> .Release(smallAreaList); }
// generate a nav mesh with one tile per zone protected void GenerateTilesForZones(AStarPathfindingWalkableArea[] walkAreas) { if (null == walkAreas || 0 == walkAreas.Length) { EB.Debug.LogWarning("GenerateTilesForZones: walkAreas is empty"); return; } LevelHelper levelHelper = GameObject.FindObjectOfType(typeof(LevelHelper)) as LevelHelper; if (null == levelHelper) { EB.Debug.LogWarning("GenerateTilesForZones: LevelHelper not found"); return; } Vector3 NavMeshBoundingBoxMin; Vector3 NavMeshBoundingBoxMax; levelHelper.CalculateAllZonesMinMax(out NavMeshBoundingBoxMin, out NavMeshBoundingBoxMax); // set the entire bounds and center of the recast graph forcedBoundsSize = NavMeshBoundingBoxMax - NavMeshBoundingBoxMin; forcedBoundsCenter = NavMeshBoundingBoxMin + (forcedBoundsSize * 0.5f); tileSizeX = tileSizeZ = (int)(EditorVars.GridSize / cellSize); // this line sets the tile size so that each tile will hold the size of a zone CalculateNumberOfTiles(ref tileXCount, ref tileZCount); #if DEBUG int correctTilesXCount = (Mathf.CeilToInt(forcedBoundsSize.x / EditorVars.GridSize)); // this would fail if GridSize is less than 1f int correctTilesZCount = (Mathf.CeilToInt(forcedBoundsSize.z / EditorVars.GridSize)); // this would fail if GridSize is less than 1f if (correctTilesXCount != tileXCount || correctTilesZCount != tileZCount) { EB.Debug.LogError("Incorrect number of tiles generated"); } #endif tiles = new NavmeshTile[tileXCount * tileZCount]; // ignore this setting scanEmptyGraph = false; Vector3 tempZoneMin = new Vector3(); Vector3 tempZoneMax = new Vector3(); // go over all the walkable areas and put there mesh into a tile foreach (AStarPathfindingWalkableArea walk in walkAreas) { ZoneDescriptor zoneDescriptor = (ZoneDescriptor)GameUtils.FindFirstComponentUpwards <ZoneDescriptor>(walk.transform); if (zoneDescriptor != null) { ZoneDescriptor.CalculateZoneMinAndMax(ref tempZoneMin, ref tempZoneMax, zoneDescriptor.gameObject.transform); // 1f is added to avoid floating point inacuracy (avoids 63.999/64 = 0, 64.99/64=1 which is correct) int z = (int)(((tempZoneMin.z + 1f) - NavMeshBoundingBoxMin.z) / EditorVars.GridSize); int x = (int)(((tempZoneMin.x + 1f) - NavMeshBoundingBoxMin.x) / EditorVars.GridSize); MeshFilter meshFilter = walk.gameObject.GetComponent <MeshFilter>(); if (null != meshFilter.sharedMesh) { // the Vector3 vertices in the mesh need to be converted to the APP Int3 format Int3[] Int3Verts = new Int3[meshFilter.sharedMesh.vertices.Length]; for (int i = 0; i < Int3Verts.Length; ++i) { Vector3 tempVert = new Vector3(meshFilter.sharedMesh.vertices[i].x, meshFilter.sharedMesh.vertices[i].y, meshFilter.sharedMesh.vertices[i].z); tempVert = walk.transform.TransformPoint(tempVert); // get the world space position, rather than local space // clamp the verts to the edges of the zone boundaries if they are close, this is so that the different tiles are linked together accurately const float Tol = 0.01f; tempVert.x = (tempVert.x <= tempZoneMin.x + Tol) ? tempZoneMin.x : tempVert.x; tempVert.x = (tempVert.x >= tempZoneMax.x - Tol) ? tempZoneMax.x : tempVert.x; tempVert.z = (tempVert.z <= tempZoneMin.z + Tol) ? tempZoneMin.z : tempVert.z; tempVert.z = (tempVert.z >= tempZoneMax.z - Tol) ? tempZoneMax.z : tempVert.z; Int3Verts[i] = (Int3)tempVert; } NavmeshTile tile = CreateTile(meshFilter.sharedMesh.triangles, Int3Verts, x, z); tiles[Convert2DArrayCoordTo1DArrayCoord(x, z, tileXCount)] = tile; } } } //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); // connect each tile to one and other for (int z = 0; z < tileZCount; z++) { for (int x = 0; x < tileXCount; x++) { // make sure all the tiles which might be considered, have tiles created CreateAndAddEmptyTileIfNonExists(x, z); CreateAndAddEmptyTileIfNonExists(x + 1, z); CreateAndAddEmptyTileIfNonExists(x, z + 1); if (x < tileXCount - 1) { ConnectTiles(tiles[Convert2DArrayCoordTo1DArrayCoord(x, z, tileXCount)], tiles[Convert2DArrayCoordTo1DArrayCoord(x + 1, z, tileXCount)]); } if (z < tileZCount - 1) { ConnectTiles(tiles[Convert2DArrayCoordTo1DArrayCoord(x, z, tileXCount)], tiles[Convert2DArrayCoordTo1DArrayCoord(x, z + 1, tileXCount)]); } } } }
/** Calls a delegate with all nodes in the graph. * This is the primary way of "looping" through all nodes in a graph. * * This function should not change anything in the graph structure. */ public abstract void GetNodes(GraphNodeDelegateCancelable del);
public void FloodFill() { #if ASTARDEBUG System.DateTime startTime = System.DateTime.UtcNow; #endif var graphs = astar.graphs; if (graphs == null) { return; } // Iterate through all nodes in all graphs // and reset their Area field for (int i = 0; i < graphs.Length; i++) { var graph = graphs[i]; if (graph != null) { graph.GetNodes(node => { node.Area = 0; return(true); }); } } lastUniqueAreaIndex = 0; uint area = 0; int forcedSmallAreas = 0; // Get a temporary stack from a pool var stack = Pathfinding.Util.StackPool <GraphNode> .Claim(); for (int i = 0; i < graphs.Length; i++) { NavGraph graph = graphs[i]; if (graph == null) { continue; } GraphNodeDelegateCancelable del = node => { if (node.Walkable && node.Area == 0) { area++; uint thisArea = area; if (area > GraphNode.MaxAreaIndex) { // Forced to consider this a small area area--; thisArea = area; // Make sure the first small area is also counted if (forcedSmallAreas == 0) { forcedSmallAreas = 1; } forcedSmallAreas++; } stack.Clear(); stack.Push(node); int counter = 1; node.Area = thisArea; while (stack.Count > 0) { counter++; stack.Pop().FloodFill(stack, thisArea); } } return(true); }; graph.GetNodes(del); } lastUniqueAreaIndex = area; if (forcedSmallAreas > 0) { Debug.LogError(forcedSmallAreas + " areas had to share IDs. " + "This usually doesn't affect pathfinding in any significant way (you might get 'Searched whole area but could not find target' as a reason for path failure) " + "however some path requests may take longer to calculate (specifically those that fail with the 'Searched whole area' error)." + "The maximum number of areas is " + GraphNode.MaxAreaIndex + "."); } // Put back into the pool Pathfinding.Util.StackPool <GraphNode> .Release(stack); #if ASTARDEBUG Debug.Log("Flood fill complete, " + area + " area" + (area > 1 ? "s" : "") + " found - " + ((System.DateTime.UtcNow.Ticks - startTime.Ticks) * 0.0001).ToString("0.00") + " ms"); #endif }
public void FloodFill() { NavGraph[] graphs = this.astar.graphs; if (graphs == null) { return; } foreach (NavGraph navGraph in graphs) { if (navGraph != null) { navGraph.GetNodes(delegate(GraphNode node) { node.Area = 0u; return(true); }); } } this.lastUniqueAreaIndex = 0u; uint area = 0u; int forcedSmallAreas = 0; Stack <GraphNode> stack = StackPool <GraphNode> .Claim(); foreach (NavGraph navGraph2 in graphs) { if (navGraph2 != null) { GraphNodeDelegateCancelable del = delegate(GraphNode node) { if (node.Walkable && node.Area == 0u) { uint area; area += 1u; area = area; if (area > 131071u) { area -= 1u; area = area; if (forcedSmallAreas == 0) { forcedSmallAreas = 1; } forcedSmallAreas++; } stack.Clear(); stack.Push(node); int num = 1; node.Area = area; while (stack.Count > 0) { num++; stack.Pop().FloodFill(stack, area); } } return(true); }; navGraph2.GetNodes(del); } } this.lastUniqueAreaIndex = area; if (forcedSmallAreas > 0) { Debug.LogError(string.Concat(new object[] { forcedSmallAreas, " areas had to share IDs. This usually doesn't affect pathfinding in any significant way (you might get 'Searched whole area but could not find target' as a reason for path failure) however some path requests may take longer to calculate (specifically those that fail with the 'Searched whole area' error).The maximum number of areas is ", 131071u, "." })); } StackPool <GraphNode> .Release(stack); }
public override void GetNodes (GraphNodeDelegateCancelable del) { if (root == null) return; root.GetNodes (del); }