public override void GetConnections(GraphNodeDelegate del) { if (this.connections == null) { return; } for (int i = 0; i < this.connections.Length; i++) { del(this.connections[i]); } }
/** Draw gizmos for the graph */ public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } // This is the relatively slow default implementation // subclasses of the base graph class may override // this method to draw gizmos in a more optimized way PathHandler data = AstarPath.active.debugPathData; GraphNode node = null; // Use this delegate to draw connections // from the #node variable to #otherNode GraphNodeDelegate drawConnection = otherNode => Gizmos.DrawLine((Vector3)node.position, (Vector3)otherNode.position); GetNodes(_node => { // Set the #node variable so that #drawConnection can use it node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } PathNode nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(drawConnection); } return(true); }); }
/** Draw gizmos for the graph */ public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } PathHandler data = AstarPath.active.debugPathData; GraphNode node = null; // Use this delegate to draw connections // from the #node variable to #otherNode GraphNodeDelegate drawConnection = otherNode => Gizmos.DrawLine((Vector3)node.position, (Vector3)otherNode.position); GetNodes(_node => { // Set the #node variable so that #drawConnection can use it node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } PathNode nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(drawConnection); } return(true); }); }
public override void GetConnections(GraphNodeDelegate del) { GridGraph gg = GetGridGraph(GraphIndex); int[] neighbourOffsets = gg.neighbourOffsets; GridNode[] nodes = gg.nodes; for (int i = 0; i < 8; i++) { if (GetConnectionInternal(i)) { GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]]; if (other != null) { del(other); } } } #if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS base.GetConnections(del); #endif }
public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } var data = AstarPath.active.debugPathData; GraphNode node = null; GraphNodeDelegate del = delegate(GraphNode o) { Gizmos.DrawLine((Vector3)node.position, (Vector3)o.position); }; GetNodes(delegate(GraphNode _node) { node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } var nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(del); } return(true); }); }
public override void GetConnections(GraphNodeDelegate del) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; if (gridNode != null) { del(gridNode); } } } if (this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { del(this.connections[j]); } } }
public override void GetConnections (GraphNodeDelegate del) { int index = NodeInGridIndex; LayerGridGraph graph = GetGridGraph (GraphIndex); int[] neighbourOffsets = graph.neighbourOffsets; LevelGridNode[] nodes = graph.nodes; for (int i=0;i<4;i++) { int conn = GetConnectionValue(i);//(gridConnections >> i*4) & 0xF; if (conn != LevelGridNode.NoConnection) { LevelGridNode other = nodes[index+neighbourOffsets[i] + graph.lastScannedWidth*graph.lastScannedDepth*conn]; if (other != null) del (other); } } }
/** Calls the delegate with all connections from this node */ public abstract void GetConnections(GraphNodeDelegate del);
public override void GetConnections (GraphNodeDelegate del) { GridGraph gg = GetGridGraph(GraphIndex); int[] neighbourOffsets = gg.neighbourOffsets; GridNode[] nodes = gg.nodes; for (int i = 0; i < 8; i++) { if (GetConnectionInternal(i)) { GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]]; if (other != null) del(other); } } #if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS if (connections != null) for (int i = 0; i < connections.Length; i++) del(connections[i]); #endif }
public override void GetConnections (GraphNodeDelegate del) { throw new System.NotImplementedException(); }
// Token: 0x06000041 RID: 65 RVA: 0x00004F38 File Offset: 0x00003338 public Vector3 Update(Vector3 position, List <Vector3> buffer, int numCorners, out bool lastCorner, out bool requiresRepath) { lastCorner = false; requiresRepath = false; Int3 @int = (Int3)position; if (this.nodes[this.currentNode].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[this.currentNode].ContainsPoint(@int)) { if (this.tmpCounter >= 10) { this.tmpCounter = 0; int i = 0; int count = this.nodes.Count; while (i < count) { if (this.nodes[i].Destroyed) { requiresRepath = true; break; } i++; } } else { this.tmpCounter++; } } else { bool flag = false; int num = this.currentNode + 1; int num2 = Math.Min(this.currentNode + 3, this.nodes.Count); while (num < num2 && !flag) { if (this.nodes[num].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[num].ContainsPoint(@int)) { this.currentNode = num; flag = true; } num++; } int num3 = this.currentNode - 1; int num4 = Math.Max(this.currentNode - 3, 0); while (num3 > num4 && !flag) { if (this.nodes[num3].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[num3].ContainsPoint(@int)) { this.currentNode = num3; flag = true; } num3--; } int num5 = 0; float num6 = float.PositiveInfinity; Vector3 vector = Vector3.zero; int num7 = 0; int count2 = this.nodes.Count; while (num7 < count2 && !flag) { if (this.nodes[num7].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[num7].ContainsPoint(@int)) { this.currentNode = num7; flag = true; vector = position; } else { Vector3 vector2 = this.nodes[num7].ClosestPointOnNodeXZ(position); float sqrMagnitude = (vector2 - position).sqrMagnitude; if (sqrMagnitude < num6) { num6 = sqrMagnitude; num5 = num7; vector = vector2; } } num7++; } this.tmpCounter = 0; int j = 0; int count3 = this.nodes.Count; while (j < count3) { if (this.nodes[j].Destroyed) { requiresRepath = true; break; } j++; } if (!flag) { vector.y = position.y; MeshNode containingPoint = null; int containingIndex = this.nodes.Count - 1; Int3 i3Copy = @int; GraphNodeDelegate del = delegate(GraphNode node) { if ((containingIndex <= 0 || node != this.nodes[containingIndex - 1]) && (containingIndex >= this.nodes.Count - 1 || node != this.nodes[containingIndex + 1])) { MeshNode meshNode2 = node as MeshNode; if (meshNode2 != null && meshNode2.ContainsPoint(i3Copy)) { containingPoint = meshNode2; } } }; while (containingIndex >= 0 && containingPoint == null) { MeshNode meshNode = this.nodes[containingIndex]; meshNode.GetConnections(del); containingIndex--; } if (containingPoint != null) { containingIndex++; this.exactStart = position; this.UpdateFunnelCorridor(containingIndex, containingPoint as TriangleMeshNode); this.currentNode = 0; } else { position = vector; this.currentNode = num5; } } } this.currentPosition = position; if (!this.FindNextCorners(position, this.currentNode, buffer, numCorners, out lastCorner)) { Debug.LogError("Oh oh"); buffer.Add(position); return(position); } return(position); }
public override void GetConnections(GraphNodeDelegate del) { throw new System.NotImplementedException(); }
public Vector3 Update(Vector3 position, List <Vector3> buffer, int numCorners, out bool lastCorner, out bool requiresRepath) { lastCorner = false; requiresRepath = false; Int3 i3Pos = (Int3)position; if (nodes[currentNode].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (nodes[currentNode].ContainsPoint(i3Pos)) { // Only check for destroyed nodes every 10 frames if (tmpCounter >= 10) { tmpCounter = 0; for (int i = 0, t = nodes.Count; i < t; i++) { if (nodes[i].Destroyed) { requiresRepath = true; break; } } } else { tmpCounter++; } } else { bool found = false; for (int i = currentNode + 1, t = System.Math.Min(currentNode + 3, nodes.Count); i < t && !found; i++) { if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (nodes[i].ContainsPoint(i3Pos)) { currentNode = i; found = true; } } for (int i = currentNode - 1, t = System.Math.Max(currentNode - 3, 0); i > t && !found; i--) { if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (nodes[i].ContainsPoint(i3Pos)) { currentNode = i; found = true; } } int closest = 0; float closestDist = float.PositiveInfinity; Vector3 closestPoint = Vector3.zero; for (int i = 0, t = nodes.Count; i < t && !found; i++) { if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (nodes[i].ContainsPoint(i3Pos)) { currentNode = i; found = true; closestPoint = position; } else { Vector3 close = nodes[i].ClosestPointOnNodeXZ(position); float d = (close - position).sqrMagnitude; if (d < closestDist) { closestDist = d; closest = i; closestPoint = close; } } } tmpCounter = 0; for (int i = 0, t = nodes.Count; i < t; i++) { if (nodes[i].Destroyed) { requiresRepath = true; break; } } if (!found) { //Debug.DrawLine (position,closestPoint,Color.cyan); //Debug.DrawRay (closestPoint,Vector3.up,Color.cyan); //Debug.Break(); closestPoint.y = position.y; MeshNode nd; MeshNode containingPoint = null; int containingIndex = nodes.Count - 1; // Need to make a copy here, the JIT will move this variable to the heap // because it is used inside a delegate, if we didn't make a copy here // we would /always/ allocate 24 bytes (sizeof(i3Pos)) on the heap every time // this method was called // now we only do it when this IF statement is executed Int3 i3Copy = i3Pos; GraphNodeDelegate del = delegate(GraphNode node) { if (!(containingIndex > 0 && node == nodes[containingIndex - 1]) && !(containingIndex < nodes.Count - 1 && node == nodes[containingIndex + 1])) { MeshNode mn = node as MeshNode; if (mn != null && mn.ContainsPoint(i3Copy)) { containingPoint = mn; } } }; for (; containingIndex >= 0 && containingPoint == null; containingIndex--) { nd = nodes[containingIndex]; nd.GetConnections(del); } if (containingPoint != null) { // It will have been decremented once after containingPoint was null, revert that containingIndex++; // We have found a node containing the position, but it is outside the funnel // Recalculate the funnel to include this node exactStart = position; UpdateFunnelCorridor(containingIndex, containingPoint as TriangleMeshNode); currentNode = 0; found = true; } else { position = closestPoint; found = true; currentNode = closest; } } } currentPosition = position; //Debug.DrawLine ((Vector3)graph.vertices[nodes[currentNode].v1] + Vector3.up*0.1f,(Vector3)graph.vertices[nodes[currentNode].v2] + Vector3.up*0.1f,Color.red); //Debug.DrawLine ((Vector3)graph.vertices[nodes[currentNode].v2] + Vector3.up*0.1f,(Vector3)graph.vertices[nodes[currentNode].v3] + Vector3.up*0.1f,Color.red); //Debug.DrawLine ((Vector3)graph.vertices[nodes[currentNode].v3] + Vector3.up*0.1f,(Vector3)graph.vertices[nodes[currentNode].v1] + Vector3.up*0.1f,Color.red); if (!FindNextCorners(position, currentNode, buffer, numCorners, out lastCorner)) { Debug.LogError("Oh oh"); buffer.Add(position); return(position); } return(position); //Debug.Log("Nearest " + w1.Elapsed.TotalMilliseconds*1000); //Debug.Log("Funnel " + w2.Elapsed.TotalMilliseconds*1000); }
Vector3 Snap (ABPath path, Exactness mode, bool start, out bool forceAddPoint) { var index = start ? 0 : path.path.Count - 1; var node = path.path[index]; var nodePos = (Vector3)node.position; forceAddPoint = false; switch (mode) { case Exactness.ClosestOnNode: return GetClampedPoint(nodePos, start ? path.startPoint : path.endPoint, node); case Exactness.SnapToNode: return nodePos; case Exactness.Original: case Exactness.Interpolate: case Exactness.NodeConnection: Vector3 relevantPoint; if (start) { relevantPoint = adjustStartPoint != null ? adjustStartPoint() : path.originalStartPoint; } else { relevantPoint = path.originalEndPoint; } switch (mode) { case Exactness.Original: return GetClampedPoint(nodePos, relevantPoint, node); case Exactness.Interpolate: var clamped = GetClampedPoint(nodePos, relevantPoint, node); // Adjacent node to either the start node or the end node in the path var adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count-1)]; return VectorMath.ClosestPointOnSegment(nodePos, (Vector3)adjacentNode.position, clamped); case Exactness.NodeConnection: // This code uses some tricks to avoid allocations // even though it uses delegates heavily // The connectionBufferAddDelegate delegate simply adds whatever node // it is called with to the connectionBuffer connectionBuffer = connectionBuffer ?? new List<GraphNode>(); connectionBufferAddDelegate = connectionBufferAddDelegate ?? (GraphNodeDelegate)connectionBuffer.Add; // Adjacent node to either the start node or the end node in the path adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count-1)]; // Add all neighbours of #node to the connectionBuffer node.GetConnections(connectionBufferAddDelegate); var bestPos = nodePos; var bestDist = float.PositiveInfinity; // Loop through all neighbours // Do it in reverse order because the length of the connectionBuffer // will change during iteration for (int i = connectionBuffer.Count - 1; i >= 0; i--) { var neighbour = connectionBuffer[i]; // Find the closest point on the connection between the nodes // and check if the distance to that point is lower than the previous best var closest = VectorMath.ClosestPointOnSegment(nodePos, (Vector3)neighbour.position, relevantPoint); var dist = (closest - relevantPoint).sqrMagnitude; if (dist < bestDist) { bestPos = closest; bestDist = dist; // If this node is not the adjacent node // then the path should go through the start node as well forceAddPoint = neighbour != adjacentNode; } } connectionBuffer.Clear(); return bestPos; default: throw new System.ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); } default: throw new System.ArgumentException("Invalid mode"); } }
public Vector3 Update(Vector3 position, List <Vector3> buffer, int numCorners, out bool lastCorner, out bool requiresRepath) { lastCorner = false; requiresRepath = false; Int3 p = (Int3)position; if (this.nodes[this.currentNode].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[this.currentNode].ContainsPoint(p)) { if (this.checkForDestroyedNodesCounter >= 10) { this.checkForDestroyedNodesCounter = 0; int i = 0; int count = this.nodes.Count; while (i < count) { if (this.nodes[i].Destroyed) { requiresRepath = true; break; } i++; } } else { this.checkForDestroyedNodesCounter++; } } else { bool flag = false; int num = this.currentNode + 1; int num2 = Math.Min(this.currentNode + 3, this.nodes.Count); while (num < num2 && !flag) { if (this.nodes[num].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[num].ContainsPoint(p)) { this.currentNode = num; flag = true; } num++; } int num3 = this.currentNode - 1; int num4 = Math.Max(this.currentNode - 3, 0); while (num3 > num4 && !flag) { if (this.nodes[num3].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (this.nodes[num3].ContainsPoint(p)) { this.currentNode = num3; flag = true; } num3--; } if (!flag) { int index = 0; int closestIsNeighbourOf = 0; float closestDist = float.PositiveInfinity; bool closestIsInPath = false; TriangleMeshNode closestNode = null; int containingIndex = this.nodes.Count - 1; this.checkForDestroyedNodesCounter = 0; int j = 0; int count2 = this.nodes.Count; while (j < count2) { if (this.nodes[j].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } Vector3 a = this.nodes[j].ClosestPointOnNode(position); float sqrMagnitude = (a - position).sqrMagnitude; if (sqrMagnitude < closestDist) { closestDist = sqrMagnitude; index = j; closestNode = this.nodes[j]; closestIsInPath = true; } j++; } Vector3 posCopy = position; GraphNodeDelegate del = delegate(GraphNode node) { if ((containingIndex <= 0 || node != this.nodes[containingIndex - 1]) && (containingIndex >= this.nodes.Count - 1 || node != this.nodes[containingIndex + 1])) { TriangleMeshNode triangleMeshNode = node as TriangleMeshNode; if (triangleMeshNode != null) { Vector3 a2 = triangleMeshNode.ClosestPointOnNode(posCopy); float sqrMagnitude2 = (a2 - posCopy).sqrMagnitude; if (sqrMagnitude2 < closestDist) { closestDist = sqrMagnitude2; closestIsNeighbourOf = containingIndex; closestNode = triangleMeshNode; closestIsInPath = false; } } } }; while (containingIndex >= 0) { this.nodes[containingIndex].GetConnections(del); containingIndex--; } if (closestIsInPath) { this.currentNode = index; position = this.nodes[index].ClosestPointOnNodeXZ(position); } else { position = closestNode.ClosestPointOnNodeXZ(position); this.exactStart = position; this.UpdateFunnelCorridor(closestIsNeighbourOf, closestNode); this.currentNode = 0; } } } this.currentPosition = position; if (!this.FindNextCorners(position, this.currentNode, buffer, numCorners, out lastCorner)) { Debug.LogError("Oh oh"); buffer.Add(position); return(position); } return(position); }
public override void GetConnections(GraphNodeDelegate del) { int nodeInGridIndex = base.NodeInGridIndex; LayerGridGraph gridGraph = LevelGridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; LevelGridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 4; i++) { int connectionValue = this.GetConnectionValue(i); if (connectionValue != 255) { LevelGridNode levelGridNode = nodes[nodeInGridIndex + neighbourOffsets[i] + gridGraph.lastScannedWidth * gridGraph.lastScannedDepth * connectionValue]; if (levelGridNode != null) { del(levelGridNode); } } } }
private Vector3 Snap(ABPath path, StartEndModifier.Exactness mode, bool start, out bool forceAddPoint) { int num = (!start) ? (path.path.Count - 1) : 0; GraphNode graphNode = path.path[num]; Vector3 vector = (Vector3)graphNode.position; forceAddPoint = false; switch (mode) { case StartEndModifier.Exactness.SnapToNode: return(vector); case StartEndModifier.Exactness.Original: case StartEndModifier.Exactness.Interpolate: case StartEndModifier.Exactness.NodeConnection: { Vector3 vector2; if (start) { vector2 = ((this.adjustStartPoint == null) ? path.originalStartPoint : this.adjustStartPoint()); } else { vector2 = path.originalEndPoint; } switch (mode) { case StartEndModifier.Exactness.Original: return(this.GetClampedPoint(vector, vector2, graphNode)); case StartEndModifier.Exactness.Interpolate: { Vector3 clampedPoint = this.GetClampedPoint(vector, vector2, graphNode); GraphNode graphNode2 = path.path[Mathf.Clamp(num + ((!start) ? -1 : 1), 0, path.path.Count - 1)]; return(VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode2.position, clampedPoint)); } case StartEndModifier.Exactness.NodeConnection: { this.connectionBuffer = (this.connectionBuffer ?? new List <GraphNode>()); GraphNodeDelegate arg_162_1; if ((arg_162_1 = this.connectionBufferAddDelegate) == null) { arg_162_1 = new GraphNodeDelegate(this.connectionBuffer.Add); } this.connectionBufferAddDelegate = arg_162_1; GraphNode graphNode2 = path.path[Mathf.Clamp(num + ((!start) ? -1 : 1), 0, path.path.Count - 1)]; graphNode.GetConnections(this.connectionBufferAddDelegate); Vector3 result = vector; float num2 = float.PositiveInfinity; for (int i = this.connectionBuffer.Count - 1; i >= 0; i--) { GraphNode graphNode3 = this.connectionBuffer[i]; Vector3 vector3 = VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode3.position, vector2); float sqrMagnitude = (vector3 - vector2).sqrMagnitude; if (sqrMagnitude < num2) { result = vector3; num2 = sqrMagnitude; forceAddPoint = (graphNode3 != graphNode2); } } this.connectionBuffer.Clear(); return(result); } } throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); } case StartEndModifier.Exactness.ClosestOnNode: return(this.GetClampedPoint(vector, (!start) ? path.endPoint : path.startPoint, graphNode)); default: throw new ArgumentException("Invalid mode"); } }
private bool ClampToNavmeshInternal(ref Vector3 position) { if (this.nodes[this.currentNode].Destroyed) { return(true); } Int3 p = (Int3)position; if (this.nodes[this.currentNode].ContainsPoint(p)) { return(false); } int i = this.currentNode + 1; int num = Math.Min(this.currentNode + 3, this.nodes.Count); while (i < num) { if (this.nodes[i].Destroyed) { return(true); } if (this.nodes[i].ContainsPoint(p)) { this.currentNode = i; return(false); } i++; } int j = this.currentNode - 1; int num2 = Math.Max(this.currentNode - 3, 0); while (j > num2) { if (this.nodes[j].Destroyed) { return(true); } if (this.nodes[j].ContainsPoint(p)) { this.currentNode = j; return(false); } j--; } int index = 0; int closestIsNeighbourOf = 0; float closestDist = float.PositiveInfinity; bool closestIsInPath = false; TriangleMeshNode closestNode = null; int containingIndex = this.nodes.Count - 1; this.checkForDestroyedNodesCounter = 0; int k = 0; int count = this.nodes.Count; while (k < count) { if (this.nodes[k].Destroyed) { return(true); } Vector3 a = this.nodes[k].ClosestPointOnNode(position); float sqrMagnitude = (a - position).sqrMagnitude; if (sqrMagnitude < closestDist) { closestDist = sqrMagnitude; index = k; closestNode = this.nodes[k]; closestIsInPath = true; } k++; } Vector3 posCopy = position; GraphNodeDelegate del = delegate(GraphNode node) { if ((containingIndex <= 0 || node != this.nodes[containingIndex - 1]) && (containingIndex >= this.nodes.Count - 1 || node != this.nodes[containingIndex + 1])) { TriangleMeshNode triangleMeshNode = node as TriangleMeshNode; if (triangleMeshNode != null) { Vector3 a2 = triangleMeshNode.ClosestPointOnNode(posCopy); float sqrMagnitude2 = (a2 - posCopy).sqrMagnitude; if (sqrMagnitude2 < closestDist) { closestDist = sqrMagnitude2; closestIsNeighbourOf = containingIndex; closestNode = triangleMeshNode; closestIsInPath = false; } } } }; while (containingIndex >= 0) { this.nodes[containingIndex].GetConnections(del); containingIndex--; } if (closestIsInPath) { this.currentNode = index; position = this.nodes[index].ClosestPointOnNodeXZ(position); } else { position = closestNode.ClosestPointOnNodeXZ(position); this.exactStart = position; this.UpdateFunnelCorridor(closestIsNeighbourOf, closestNode); this.currentNode = 0; } return(false); }
public Vector3 Update(Vector3 position, List <Vector3> buffer, int numCorners, out bool lastCorner, out bool requiresRepath) { lastCorner = false; requiresRepath = false; var i3Pos = (Int3)position; if (nodes[currentNode].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } // Check if we are in the same node as we were in during the last frame if (nodes[currentNode].ContainsPoint(i3Pos)) { // Only check for destroyed nodes every 10 frames if (checkForDestroyedNodesCounter >= 10) { checkForDestroyedNodesCounter = 0; // Loop through all nodes and check if they are destroyed // If so, we really need a recalculation of our path quickly // since there might be an obstacle blocking our path after // a graph update or something similar for (int i = 0, t = nodes.Count; i < t; i++) { if (nodes[i].Destroyed) { requiresRepath = true; break; } } } else { checkForDestroyedNodesCounter++; } } else { // This part of the code is relatively seldom called // Most of the time we are still on the same node as during the previous frame // Otherwise check the 2 nodes ahead and 2 nodes back // If they contain the node in XZ space, then we probably moved into those nodes bool found = false; // 2 nodes ahead for (int i = currentNode + 1, t = System.Math.Min(currentNode + 3, nodes.Count); i < t && !found; i++) { // If the node is destroyed, make sure we recalculate a new path quickly if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } // We found a node which contains our current position in XZ space if (nodes[i].ContainsPoint(i3Pos)) { currentNode = i; found = true; } } // 2 nodes behind for (int i = currentNode - 1, t = System.Math.Max(currentNode - 3, 0); i > t && !found; i--) { if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } if (nodes[i].ContainsPoint(i3Pos)) { currentNode = i; found = true; } } if (!found) { int closestNodeInPath = 0; int closestIsNeighbourOf = 0; float closestDist = float.PositiveInfinity; bool closestIsInPath = false; TriangleMeshNode closestNode = null; int containingIndex = nodes.Count - 1; // If we still couldn't find a good node // Check all nodes in the whole path // We are checking for if any node is destroyed in the loop // So we can reset this counter checkForDestroyedNodesCounter = 0; for (int i = 0, t = nodes.Count; i < t; i++) { if (nodes[i].Destroyed) { requiresRepath = true; lastCorner = false; buffer.Add(position); return(position); } Vector3 close = nodes[i].ClosestPointOnNode(position); float d = (close - position).sqrMagnitude; if (d < closestDist) { closestDist = d; closestNodeInPath = i; closestNode = nodes[i]; closestIsInPath = true; } } // Loop through all neighbours of all nodes in the path // and find the closet point on them // We cannot just look on the ones in the path since it is impossible // to know if we are outside the navmesh completely or if we have just // stepped in to an adjacent node // Need to make a copy here, the JIT will move this variable to the heap // because it is used inside a delegate, if we didn't make a copy here // we would *always* allocate 24 bytes (sizeof(position)) on the heap every time // this method was called // now we only do it when this IF statement is executed var posCopy = position; GraphNodeDelegate del = node => { // Check so that this neighbour we are processing is neither the node after the current node or the node before the current node in the path // This is done for optimization, we have already checked those nodes earlier if (!(containingIndex > 0 && node == nodes[containingIndex - 1]) && !(containingIndex < nodes.Count - 1 && node == nodes[containingIndex + 1])) { // Check if the neighbour was a mesh node var mn = node as TriangleMeshNode; if (mn != null) { // Find the distance to the closest point on it from our current position var close = mn.ClosestPointOnNode(posCopy); float d = (close - posCopy).sqrMagnitude; // Is that distance better than the best distance seen so far if (d < closestDist) { closestDist = d; closestIsNeighbourOf = containingIndex; closestNode = mn; closestIsInPath = false; } } } }; // Loop through all the nodes in the path in reverse order // The callback needs to know about the index, so we store it // in a local variable which it can read for (; containingIndex >= 0; containingIndex--) { // Loop through all neighbours of the node nodes[containingIndex].GetConnections(del); } // Check if the closest node // was on the path already or if we need to adjust it if (closestIsInPath) { // If we have found a node // Snap to the closest point in XZ space (keep the Y coordinate) // If we would have snapped to the closest point in 3D space, the agent // might slow down when traversing slopes currentNode = closestNodeInPath; position = nodes[closestNodeInPath].ClosestPointOnNodeXZ(position); } else { // Snap to the closest point in XZ space on the node position = closestNode.ClosestPointOnNodeXZ(position); // We have found a node containing the position, but it is outside the funnel // Recalculate the funnel to include this node exactStart = position; UpdateFunnelCorridor(closestIsNeighbourOf, closestNode); // Restart from the first node in the updated path currentNode = 0; } } } currentPosition = position; if (!FindNextCorners(position, currentNode, buffer, numCorners, out lastCorner)) { Debug.LogError("Oh oh"); buffer.Add(position); return(position); } return(position); }
Vector3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint) { var index = start ? 0 : path.path.Count - 1; var node = path.path[index]; var nodePos = (Vector3)node.position; forceAddPoint = false; switch (mode) { case Exactness.ClosestOnNode: return(GetClampedPoint(nodePos, start ? path.startPoint : path.endPoint, node)); case Exactness.SnapToNode: return(nodePos); case Exactness.Original: case Exactness.Interpolate: case Exactness.NodeConnection: Vector3 relevantPoint; if (start) { relevantPoint = adjustStartPoint != null?adjustStartPoint() : path.originalStartPoint; } else { relevantPoint = path.originalEndPoint; } switch (mode) { case Exactness.Original: return(GetClampedPoint(nodePos, relevantPoint, node)); case Exactness.Interpolate: var clamped = GetClampedPoint(nodePos, relevantPoint, node); // Adjacent node to either the start node or the end node in the path var adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)]; return(VectorMath.ClosestPointOnSegment(nodePos, (Vector3)adjacentNode.position, clamped)); case Exactness.NodeConnection: // This code uses some tricks to avoid allocations // even though it uses delegates heavily // The connectionBufferAddDelegate delegate simply adds whatever node // it is called with to the connectionBuffer connectionBuffer = connectionBuffer ?? new List <GraphNode>(); connectionBufferAddDelegate = connectionBufferAddDelegate ?? (GraphNodeDelegate)connectionBuffer.Add; // Adjacent node to either the start node or the end node in the path adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)]; // Add all neighbours of #node to the connectionBuffer node.GetConnections(connectionBufferAddDelegate); var bestPos = nodePos; var bestDist = float.PositiveInfinity; // Loop through all neighbours // Do it in reverse order because the length of the connectionBuffer // will change during iteration for (int i = connectionBuffer.Count - 1; i >= 0; i--) { var neighbour = connectionBuffer[i]; // Find the closest point on the connection between the nodes // and check if the distance to that point is lower than the previous best var closest = VectorMath.ClosestPointOnSegment(nodePos, (Vector3)neighbour.position, relevantPoint); var dist = (closest - relevantPoint).sqrMagnitude; if (dist < bestDist) { bestPos = closest; bestDist = dist; // If this node is not the adjacent node // then the path should go through the start node as well forceAddPoint = neighbour != adjacentNode; } } connectionBuffer.Clear(); return(bestPos); default: throw new System.ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); } default: throw new System.ArgumentException("Invalid mode"); } }
public abstract void GetConnections(GraphNodeDelegate del);
public override void GetConnections (GraphNodeDelegate del) { GridGraph gg = GetGridGraph (GraphIndex); int[] neighbourOffsets = gg.neighbourOffsets; GridNode[] nodes = gg.nodes; for (int i=0;i<8;i++) { if (GetConnectionInternal(i)) { GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]]; if (other != null) del (other); } } }
public override void GetConnections (GraphNodeDelegate del) { if (connections == null) return; for (int i=0;i<connections.Length;i++) del (connections[i]); }
private Vector3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint) { Vector3 originalEndPoint; GraphNode node2; int num = !start ? (path.path.Count - 1) : 0; GraphNode hint = path.path[num]; Vector3 position = (Vector3)hint.position; forceAddPoint = false; switch (mode) { case Exactness.SnapToNode: return(position); case Exactness.Original: case Exactness.Interpolate: case Exactness.NodeConnection: if (!start) { originalEndPoint = path.originalEndPoint; break; } originalEndPoint = (this.adjustStartPoint == null) ? path.originalStartPoint : this.adjustStartPoint(); break; case Exactness.ClosestOnNode: return(this.GetClampedPoint(position, !start ? path.endPoint : path.startPoint, hint)); default: throw new ArgumentException("Invalid mode"); } switch (mode) { case Exactness.Original: return(this.GetClampedPoint(position, originalEndPoint, hint)); case Exactness.Interpolate: { Vector3 point = this.GetClampedPoint(position, originalEndPoint, hint); node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)]; return(VectorMath.ClosestPointOnSegment(position, (Vector3)node2.position, point)); } case Exactness.NodeConnection: { if (this.connectionBuffer == null) { } this.connectionBuffer = new List <GraphNode>(); if (this.connectionBufferAddDelegate == null) { } this.connectionBufferAddDelegate = new GraphNodeDelegate(this.connectionBuffer.Add); node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)]; hint.GetConnections(this.connectionBufferAddDelegate); Vector3 vector4 = position; float positiveInfinity = float.PositiveInfinity; for (int i = this.connectionBuffer.Count - 1; i >= 0; i--) { GraphNode node3 = this.connectionBuffer[i]; Vector3 vector5 = VectorMath.ClosestPointOnSegment(position, (Vector3)node3.position, originalEndPoint); Vector3 vector6 = vector5 - originalEndPoint; float sqrMagnitude = vector6.sqrMagnitude; if (sqrMagnitude < positiveInfinity) { vector4 = vector5; positiveInfinity = sqrMagnitude; forceAddPoint = node3 != node2; } } this.connectionBuffer.Clear(); return(vector4); } } throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); }