public IEnumerator UpdateGraph() { Vector3 dir = this.target.position - this.graph.center; dir.x = Mathf.Round(dir.x / this.graph.nodeSize) * this.graph.nodeSize; dir.z = Mathf.Round(dir.z / this.graph.nodeSize) * this.graph.nodeSize; dir.y = 0f; if (dir == Vector3.zero) { yield break; } Int2 offset = new Int2(-Mathf.RoundToInt(dir.x / this.graph.nodeSize), -Mathf.RoundToInt(dir.z / this.graph.nodeSize)); this.graph.center += dir; this.graph.GenerateMatrix(); if (this.tmp == null || this.tmp.Length != this.graph.nodes.Length) { this.tmp = new GridNode[this.graph.nodes.Length]; } int width = this.graph.width; int depth = this.graph.depth; GridNode[] nodes = this.graph.nodes; if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth) { for (int i = 0; i < depth; i++) { int num = i * width; int num2 = (i + offset.y + depth) % depth * width; for (int j = 0; j < width; j++) { this.tmp[num2 + (j + offset.x + width) % width] = nodes[num + j]; } } yield return(null); for (int k = 0; k < depth; k++) { int num3 = k * width; for (int l = 0; l < width; l++) { GridNode gridNode = this.tmp[num3 + l]; gridNode.NodeInGridIndex = num3 + l; nodes[num3 + l] = gridNode; } } IntRect r = new IntRect(0, 0, offset.x, offset.y); int minz = r.ymax; int maxz = depth; if (r.xmin > r.xmax) { int xmax = r.xmax; r.xmax = width + r.xmin; r.xmin = width + xmax; } if (r.ymin > r.ymax) { int ymax = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + ymax; minz = 0; maxz = r.ymin; } r = r.Expand(this.graph.erodeIterations + 1); r = IntRect.Intersection(r, new IntRect(0, 0, width, depth)); yield return(null); for (int m = r.ymin; m < r.ymax; m++) { for (int n = 0; n < width; n++) { this.graph.UpdateNodePositionCollision(nodes[m * width + n], n, m, false); } } yield return(null); for (int num4 = minz; num4 < maxz; num4++) { for (int num5 = r.xmin; num5 < r.xmax; num5++) { this.graph.UpdateNodePositionCollision(nodes[num4 * width + num5], num5, num4, false); } } yield return(null); for (int num6 = r.ymin; num6 < r.ymax; num6++) { for (int num7 = 0; num7 < width; num7++) { this.graph.CalculateConnections(nodes, num7, num6, nodes[num6 * width + num7]); } } yield return(null); for (int num8 = minz; num8 < maxz; num8++) { for (int num9 = r.xmin; num9 < r.xmax; num9++) { this.graph.CalculateConnections(nodes, num9, num8, nodes[num8 * width + num9]); } } yield return(null); for (int num10 = 0; num10 < depth; num10++) { for (int num11 = 0; num11 < width; num11++) { if (num11 == 0 || num10 == 0 || num11 >= width - 1 || num10 >= depth - 1) { this.graph.CalculateConnections(nodes, num11, num10, nodes[num10 * width + num11]); } } } } else { for (int num12 = 0; num12 < depth; num12++) { for (int num13 = 0; num13 < width; num13++) { this.graph.UpdateNodePositionCollision(nodes[num12 * width + num13], num13, num12, false); } } for (int num14 = 0; num14 < depth; num14++) { for (int num15 = 0; num15 < width; num15++) { this.graph.CalculateConnections(nodes, num15, num14, nodes[num14 * width + num15]); } } } if (this.floodFill) { yield return(null); AstarPath.active.QueueWorkItemFloodFill(); } yield break; }
/** Async method for moving the graph */ IEnumerator UpdateGraphCoroutine () { // Find the direction // that we want to move the graph in. // Calcuculate this in graph space (where a distance of one is the size of one node) Vector3 dir = PointToGraphSpace(target.position) - PointToGraphSpace(graph.center); // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x); dir.z = Mathf.Round(dir.z); dir.y = 0; // Nothing do to if ( dir == Vector3.zero ) yield break; // Number of nodes to offset in each direction Int2 offset = new Int2(-Mathf.RoundToInt(dir.x), -Mathf.RoundToInt(dir.z)); // Move the center (this is in world units, so we need to convert it back from graph space) graph.center += graph.matrix.MultiplyVector (dir); graph.GenerateMatrix (); // Create a temporary buffer // required for the calculations if ( tmp == null || tmp.Length != graph.nodes.Length ) { tmp = new GridNode[graph.nodes.Length]; } // Cache some variables for easier access int width = graph.width; int depth = graph.depth; GridNode[] nodes = graph.nodes; // Check if we have moved // less than a whole graph // width in any direction if ( Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth ) { // Offset each node by the #offset variable // nodes which would end up outside the graph // will wrap around to the other side of it for ( int z=0; z < depth; z++ ) { int pz = z*width; int tz = ((z+offset.y + depth)%depth)*width; for ( int x=0; x < width; x++ ) { tmp[tz + ((x+offset.x + width) % width)] = nodes[pz + x]; } } yield return null; // Copy the nodes back to the graph // and set the correct indices for ( int z=0; z < depth; z++ ) { int pz = z*width; for ( int x=0; x < width; x++ ) { GridNode node = tmp[pz + x]; node.NodeInGridIndex = pz + x; nodes[pz + x] = node; } } IntRect r = new IntRect ( 0, 0, offset.x, offset.y ); int minz = r.ymax; int maxz = depth; // If offset.x < 0, adjust the rect if ( r.xmin > r.xmax ) { int tmp2 = r.xmax; r.xmax = width + r.xmin; r.xmin = width + tmp2; } // If offset.y < 0, adjust the rect if ( r.ymin > r.ymax ) { int tmp2 = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + tmp2; minz = 0; maxz = r.ymin; } // Make sure erosion is taken into account // Otherwise we would end up with ugly artifacts r = r.Expand ( graph.erodeIterations + 1 ); // Makes sure the rect stays inside the grid r = IntRect.Intersection ( r, new IntRect ( 0, 0, width, depth ) ); yield return null; // Update all nodes along one edge of the graph // With the same width as the rect for ( int z = r.ymin; z < r.ymax; z++ ) { for ( int x = 0; x < width; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } yield return null; // Update all nodes along the other edge of the graph // With the same width as the rect for ( int z = minz; z < maxz; z++ ) { for ( int x = r.xmin; x < r.xmax; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } yield return null; // Calculate all connections for the nodes // that might have changed for ( int z = r.ymin; z < r.ymax; z++ ) { for ( int x = 0; x < width; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } yield return null; // Calculate all connections for the nodes // that might have changed for ( int z = minz; z < maxz; z++ ) { for ( int x = r.xmin; x < r.xmax; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } yield return null; // Calculate all connections for the nodes along the boundary // of the graph, these always need to be updated /** \todo Optimize to not traverse all nodes in the graph, only those at the edges */ for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { if ( x == 0 || z == 0 || x >= width-1 || z >= depth-1 ) graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } } else { // Just update all nodes for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } // Recalculate the connections of all nodes for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } } if ( floodFill ) { yield return null; // Make sure the areas for the graph // have been recalculated // not doing this can cause pathfinding to fail AstarPath.active.QueueWorkItemFloodFill (); } }
IEnumerator UpdateGraphCoroutine() { // Find the direction // that we want to move the graph in var dir = target.position - graph.center; // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x / graph.nodeSize) * graph.nodeSize; dir.z = Mathf.Round(dir.z / graph.nodeSize) * graph.nodeSize; dir.y = 0; // Nothing do to if (dir == Vector3.zero) { yield break; } // Number of nodes to offset in each // direction var offset = new Int2(-Mathf.RoundToInt(dir.x / graph.nodeSize), -Mathf.RoundToInt(dir.z / graph.nodeSize)); // Move the center graph.center += dir; graph.GenerateMatrix(); // Create a temporary buffer // required for the calculations if (tmp == null || tmp.Length != graph.nodes.Length) { tmp = new GridNode[graph.nodes.Length]; } // Cache some variables for easier access var width = graph.width; var depth = graph.depth; var nodes = graph.nodes; // Check if we have moved // less than a whole graph // width in any direction if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth) { // Offset each node by the #offset variable // nodes which would end up outside the graph // will wrap around to the other side of it for (var z = 0; z < depth; z++) { var pz = z * width; var tz = ((z + offset.y + depth) % depth) * width; for (var x = 0; x < width; x++) { tmp[tz + ((x + offset.x + width) % width)] = nodes[pz + x]; } } yield return(null); // Copy the nodes back to the graph // and set the correct indices for (var z = 0; z < depth; z++) { var pz = z * width; for (var x = 0; x < width; x++) { var node = tmp[pz + x]; node.NodeInGridIndex = pz + x; nodes[pz + x] = node; } } var r = new IntRect(0, 0, offset.x, offset.y); var minz = r.ymax; var maxz = depth; // If offset.x < 0, adjust the rect if (r.xmin > r.xmax) { var tmp2 = r.xmax; r.xmax = width + r.xmin; r.xmin = width + tmp2; } // If offset.y < 0, adjust the rect if (r.ymin > r.ymax) { var tmp2 = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + tmp2; minz = 0; maxz = r.ymin; } // Make sure erosion is taken into account // Otherwise we would end up with ugly artifacts r = r.Expand(graph.erodeIterations + 1); // Makes sure the rect stays inside the grid r = IntRect.Intersection(r, new IntRect(0, 0, width, depth)); yield return(null); // Update all nodes along one edge of the graph // With the same width as the rect for (var z = r.ymin; z < r.ymax; z++) { for (var x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); // Update all nodes along the other edge of the graph // With the same width as the rect for (var z = minz; z < maxz; z++) { for (var x = r.xmin; x < r.xmax; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); // Calculate all connections for the nodes // that might have changed for (var z = r.ymin; z < r.ymax; z++) { for (var x = 0; x < width; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } yield return(null); // Calculate all connections for the nodes // that might have changed for (var z = minz; z < maxz; z++) { for (var x = r.xmin; x < r.xmax; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } yield return(null); // Calculate all connections for the nodes along the boundary // of the graph, these always need to be updated /** \todo Optimize to not traverse all nodes in the graph, only those at the edges */ for (var z = 0; z < depth; z++) { for (var x = 0; x < width; x++) { if (x == 0 || z == 0 || x >= width - 1 || z >= depth - 1) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } } } else { // Just update all nodes for (var z = 0; z < depth; z++) { for (var x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } // Recalculate the connections of all nodes for (var z = 0; z < depth; z++) { for (var x = 0; x < width; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } } if (floodFill) { yield return(null); // Make sure the areas for the graph // have been recalculated // not doing this can cause pathfinding to fail AstarPath.active.QueueWorkItemFloodFill(); } }
/** Async method for moving the graph */ IEnumerator UpdateGraphCoroutine() { // Find the direction that we want to move the graph in. // Calcuculate this in graph space (where a distance of one is the size of one node) Vector3 dir = PointToGraphSpace(target.position) - PointToGraphSpace(graph.center); // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x); dir.z = Mathf.Round(dir.z); dir.y = 0; // Nothing do to if (dir == Vector3.zero) { yield break; } // Number of nodes to offset in each direction Int2 offset = new Int2(-Mathf.RoundToInt(dir.x), -Mathf.RoundToInt(dir.z)); // Move the center (this is in world units, so we need to convert it back from graph space) graph.center += graph.transform.TransformVector(dir); graph.UpdateTransform(); // Cache some variables for easier access int width = graph.width; int depth = graph.depth; GridNodeBase[] nodes; // Layers are required when handling LayeredGridGraphs int layers = 1; nodes = graph.nodes; // Create a temporary buffer required for the calculations if (buffer == null || buffer.Length != width * depth) { buffer = new GridNodeBase[width * depth]; } // Check if we have moved less than a whole graph width all directions // If we have moved more than this we can just as well recalculate the whole graph if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth) { IntRect recalculateRect = new IntRect(0, 0, offset.x, offset.y); // If offset.x < 0, adjust the rect if (recalculateRect.xmin > recalculateRect.xmax) { int tmp2 = recalculateRect.xmax; recalculateRect.xmax = width + recalculateRect.xmin; recalculateRect.xmin = width + tmp2; } // If offset.y < 0, adjust the rect if (recalculateRect.ymin > recalculateRect.ymax) { int tmp2 = recalculateRect.ymax; recalculateRect.ymax = depth + recalculateRect.ymin; recalculateRect.ymin = depth + tmp2; } // Connections need to be recalculated for the neighbours as well, so we need to expand the rect by 1 var connectionRect = recalculateRect.Expand(1); // Makes sure the rect stays inside the grid connectionRect = IntRect.Intersection(connectionRect, new IntRect(0, 0, width, depth)); // Offset each node by the #offset variable // nodes which would end up outside the graph // will wrap around to the other side of it for (int l = 0; l < layers; l++) { int layerOffset = l * width * depth; for (int z = 0; z < depth; z++) { int pz = z * width; int tz = ((z + offset.y + depth) % depth) * width; for (int x = 0; x < width; x++) { buffer[tz + ((x + offset.x + width) % width)] = nodes[layerOffset + pz + x]; } } yield return(null); // Copy the nodes back to the graph // and set the correct indices for (int z = 0; z < depth; z++) { int pz = z * width; for (int x = 0; x < width; x++) { int newIndex = pz + x; var node = buffer[newIndex]; if (node != null) { node.NodeInGridIndex = newIndex; } nodes[layerOffset + newIndex] = node; } // Calculate the limits for the region that has been wrapped // to the other side of the graph int xmin, xmax; if (z >= recalculateRect.ymin && z < recalculateRect.ymax) { xmin = 0; xmax = depth; } else { xmin = recalculateRect.xmin; xmax = recalculateRect.xmax; } for (int x = xmin; x < xmax; x++) { var node = buffer[pz + x]; if (node != null) { // Clear connections on all nodes that are wrapped and placed on the other side of the graph. // This is both to clear any custom connections (which do not really make sense after moving the node) // and to prevent possible exceptions when the node will later (possibly) be destroyed because it was // not needed anymore (only for layered grid graphs). node.ClearConnections(false); } } } yield return(null); } // The calculation will only update approximately this number of // nodes per frame. This is used to keep CPU load per frame low int yieldEvery = 1000; // To avoid the update taking too long, make yieldEvery somewhat proportional to the number of nodes that we are going to update int approxNumNodesToUpdate = Mathf.Max(Mathf.Abs(offset.x), Mathf.Abs(offset.y)) * Mathf.Max(width, depth); yieldEvery = Mathf.Max(yieldEvery, approxNumNodesToUpdate / 10); int counter = 0; // Recalculate the nodes // Take a look at the image in the docs for the UpdateGraph method // to see which nodes are being recalculated. for (int z = 0; z < depth; z++) { int xmin, xmax; if (z >= recalculateRect.ymin && z < recalculateRect.ymax) { xmin = 0; xmax = width; } else { xmin = recalculateRect.xmin; xmax = recalculateRect.xmax; } for (int x = xmin; x < xmax; x++) { graph.RecalculateCell(x, z, false, false); } counter += (xmax - xmin); if (counter > yieldEvery) { counter = 0; yield return(null); } } for (int z = 0; z < depth; z++) { int xmin, xmax; if (z >= connectionRect.ymin && z < connectionRect.ymax) { xmin = 0; xmax = width; } else { xmin = connectionRect.xmin; xmax = connectionRect.xmax; } for (int x = xmin; x < xmax; x++) { graph.CalculateConnections(x, z); } counter += (xmax - xmin); if (counter > yieldEvery) { counter = 0; yield return(null); } } yield return(null); // Calculate all connections for the nodes along the boundary // of the graph, these always need to be updated /** \todo Optimize to not traverse all nodes in the graph, only those at the edges */ for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { if (x == 0 || z == 0 || x == width - 1 || z == depth - 1) { graph.CalculateConnections(x, z); } } } // We need to clear the Area if we are not using flood filling. // This will make pathfinding always work, but it may be slow // to figure out that no path exists if none does. // (of course, if there are regions between which no valid // paths exist, then the #floodFill field should not // be set to false anyway). if (!floodFill) { graph.GetNodes(node => node.Area = 1); } } else { // The calculation will only update approximately this number of // nodes per frame. This is used to keep CPU load per frame low int yieldEvery = Mathf.Max(depth * width / 20, 1000); int counter = 0; // Just update all nodes for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.RecalculateCell(x, z); } counter += width; if (counter > yieldEvery) { counter = 0; yield return(null); } } // Recalculate the connections of all nodes for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.CalculateConnections(x, z); } counter += width; if (counter > yieldEvery) { counter = 0; yield return(null); } } } }
public IEnumerator UpdateGraph () { Vector3 dir = target.position - graph.center; // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x/graph.nodeSize)*graph.nodeSize; dir.z = Mathf.Round(dir.z/graph.nodeSize)*graph.nodeSize; dir.y = 0; if ( dir == Vector3.zero ) yield break; Int2 offset = new Int2 ( -Mathf.RoundToInt(dir.x/graph.nodeSize), -Mathf.RoundToInt(dir.z/graph.nodeSize) ); // Move the center graph.center += dir; graph.GenerateMatrix (); if ( tmp == null || tmp.Length != graph.nodes.Length ) { tmp = new GridNode[graph.nodes.Length]; } int width = graph.width; int depth = graph.depth; GridNode[] nodes = graph.nodes; if ( Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth ) { for ( int z=0; z < depth; z++ ) { int pz = z*width; int tz = ((z+offset.y + depth)%depth)*width; for ( int x=0; x < width; x++ ) { tmp[tz + ((x+offset.x + width) % width)] = nodes[pz + x]; } } yield return null; for ( int z=0; z < depth; z++ ) { int pz = z*width; for ( int x=0; x < width; x++ ) { GridNode node = tmp[pz + x]; node.NodeInGridIndex = pz + x; nodes[pz + x] = node; } } IntRect r = new IntRect ( 0, 0, offset.x, offset.y ); int minz = r.ymax; int maxz = depth; if ( r.xmin > r.xmax ) { int tmp2 = r.xmax; r.xmax = width + r.xmin; r.xmin = width + tmp2; } if ( r.ymin > r.ymax ) { int tmp2 = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + tmp2; minz = 0; maxz = r.ymin; } //Debug.Log ( "R1 " + r ); r = r.Expand ( graph.erodeIterations + 1 ); r = IntRect.Intersection ( r, new IntRect ( 0, 0, width, depth ) ); //Debug.Log ( "R2 " + r ); yield return null; for ( int z = r.ymin; z < r.ymax; z++ ) { for ( int x = 0; x < width; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } yield return null; for ( int z = minz; z < maxz; z++ ) { for ( int x = r.xmin; x < r.xmax; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } yield return null; for ( int z = r.ymin; z < r.ymax; z++ ) { for ( int x = 0; x < width; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } yield return null; for ( int z = minz; z < maxz; z++ ) { for ( int x = r.xmin; x < r.xmax; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } yield return null; for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { if ( x == 0 || z == 0 || x >= width-1 || z >= depth-1 ) graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } } else { for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { graph.UpdateNodePositionCollision ( nodes[z*width + x], x, z, false ); } } for ( int z = 0; z < depth; z++ ) { for ( int x = 0; x < width; x++ ) { graph.CalculateConnections (nodes, x, z, nodes[z*width+x]); } } } if ( floodFill ) { yield return null; AstarPath.active.QueueWorkItemFloodFill (); } }
/** Async method for moving the graph */ IEnumerator UpdateGraphCoroutine() { // Find the direction // that we want to move the graph in. // Calcuculate this in graph space (where a distance of one is the size of one node) Vector3 dir = PointToGraphSpace(target.position) - PointToGraphSpace(graph.center); // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x); dir.z = Mathf.Round(dir.z); dir.y = 0; // Nothing do to if (dir == Vector3.zero) { yield break; } // Number of nodes to offset in each direction Int2 offset = new Int2(-Mathf.RoundToInt(dir.x), -Mathf.RoundToInt(dir.z)); // Move the center (this is in world units, so we need to convert it back from graph space) graph.center += graph.matrix.MultiplyVector(dir); graph.GenerateMatrix(); // Create a temporary buffer // required for the calculations if (tmp == null || tmp.Length != graph.nodes.Length) { tmp = new GridNode[graph.nodes.Length]; } // Cache some variables for easier access int width = graph.width; int depth = graph.depth; GridNode[] nodes = graph.nodes; // Check if we have moved // less than a whole graph // width in any direction if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth) { // Offset each node by the #offset variable // nodes which would end up outside the graph // will wrap around to the other side of it for (int z = 0; z < depth; z++) { int pz = z * width; int tz = ((z + offset.y + depth) % depth) * width; for (int x = 0; x < width; x++) { tmp[tz + ((x + offset.x + width) % width)] = nodes[pz + x]; } } yield return(null); // Copy the nodes back to the graph // and set the correct indices for (int z = 0; z < depth; z++) { int pz = z * width; for (int x = 0; x < width; x++) { GridNode node = tmp[pz + x]; node.NodeInGridIndex = pz + x; nodes[pz + x] = node; } } IntRect r = new IntRect(0, 0, offset.x, offset.y); int minz = r.ymax; int maxz = depth; // If offset.x < 0, adjust the rect if (r.xmin > r.xmax) { int tmp2 = r.xmax; r.xmax = width + r.xmin; r.xmin = width + tmp2; } // If offset.y < 0, adjust the rect if (r.ymin > r.ymax) { int tmp2 = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + tmp2; minz = 0; maxz = r.ymin; } // Make sure erosion is taken into account // Otherwise we would end up with ugly artifacts r = r.Expand(graph.erodeIterations + 1); // Makes sure the rect stays inside the grid r = IntRect.Intersection(r, new IntRect(0, 0, width, depth)); yield return(null); // Update all nodes along one edge of the graph // With the same width as the rect for (int z = r.ymin; z < r.ymax; z++) { for (int x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); // Update all nodes along the other edge of the graph // With the same width as the rect for (int z = minz; z < maxz; z++) { for (int x = r.xmin; x < r.xmax; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); // Calculate all connections for the nodes // that might have changed for (int z = r.ymin; z < r.ymax; z++) { for (int x = 0; x < width; x++) { graph.CalculateConnections(x, z, nodes[z * width + x]); } } yield return(null); // Calculate all connections for the nodes // that might have changed for (int z = minz; z < maxz; z++) { for (int x = r.xmin; x < r.xmax; x++) { graph.CalculateConnections(x, z, nodes[z * width + x]); } } yield return(null); // Calculate all connections for the nodes along the boundary // of the graph, these always need to be updated /** \todo Optimize to not traverse all nodes in the graph, only those at the edges */ for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { if (x == 0 || z == 0 || x >= width - 1 || z >= depth - 1) { graph.CalculateConnections(x, z, nodes[z * width + x]); } } } } else { // Just update all nodes for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } // Recalculate the connections of all nodes for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } } yield return(null); }
public IEnumerator UpdateGraph() { Vector3 dir = target.position - graph.center; // Snap to a whole number of nodes dir.x = Mathf.Round(dir.x / graph.nodeSize) * graph.nodeSize; dir.z = Mathf.Round(dir.z / graph.nodeSize) * graph.nodeSize; dir.y = 0; if (dir == Vector3.zero) { yield break; } Int2 offset = new Int2(-Mathf.RoundToInt(dir.x / graph.nodeSize), -Mathf.RoundToInt(dir.z / graph.nodeSize)); // Move the center graph.center += dir; graph.GenerateMatrix(); if (tmp == null || tmp.Length != graph.nodes.Length) { tmp = new GridNode[graph.nodes.Length]; } int width = graph.width; int depth = graph.depth; GridNode[] nodes = graph.nodes; if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth) { for (int z = 0; z < depth; z++) { int pz = z * width; int tz = ((z + offset.y + depth) % depth) * width; for (int x = 0; x < width; x++) { tmp[tz + ((x + offset.x + width) % width)] = nodes[pz + x]; } } yield return(null); for (int z = 0; z < depth; z++) { int pz = z * width; for (int x = 0; x < width; x++) { GridNode node = tmp[pz + x]; node.NodeInGridIndex = pz + x; nodes[pz + x] = node; } } IntRect r = new IntRect(0, 0, offset.x, offset.y); int minz = r.ymax; int maxz = depth; if (r.xmin > r.xmax) { int tmp2 = r.xmax; r.xmax = width + r.xmin; r.xmin = width + tmp2; } if (r.ymin > r.ymax) { int tmp2 = r.ymax; r.ymax = depth + r.ymin; r.ymin = depth + tmp2; minz = 0; maxz = r.ymin; } //Debug.Log ( "R1 " + r ); r = r.Expand(graph.erodeIterations + 1); r = IntRect.Intersection(r, new IntRect(0, 0, width, depth)); //Debug.Log ( "R2 " + r ); yield return(null); for (int z = r.ymin; z < r.ymax; z++) { for (int x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); for (int z = minz; z < maxz; z++) { for (int x = r.xmin; x < r.xmax; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } yield return(null); for (int z = r.ymin; z < r.ymax; z++) { for (int x = 0; x < width; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } yield return(null); for (int z = minz; z < maxz; z++) { for (int x = r.xmin; x < r.xmax; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } yield return(null); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { if (x == 0 || z == 0 || x >= width - 1 || z >= depth - 1) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } } } else { for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.UpdateNodePositionCollision(nodes[z * width + x], x, z, false); } } for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { graph.CalculateConnections(nodes, x, z, nodes[z * width + x]); } } } if (floodFill) { yield return(null); AstarPath.active.QueueWorkItemFloodFill(); } }