//public GameObject meshRenderer; public override void OnInspectorGUI(NavGraph target) { NavMeshGraph graph = target as NavMeshGraph; #if UNITY_3_3 graph.sourceMesh = EditorGUILayout.ObjectField("Source Mesh", graph.sourceMesh, typeof(Mesh)) as Mesh; #else graph.sourceMesh = EditorGUILayout.ObjectField("Source Mesh", graph.sourceMesh, typeof(Mesh), true) as Mesh; #endif graph.offset = EditorGUILayout.Vector3Field("Offset", graph.offset); graph.rotation = EditorGUILayout.Vector3Field("Rotation", graph.rotation); graph.scale = EditorGUILayout.FloatField("Scale", graph.scale); graph.scale = (graph.scale <0.01F && graph.scale> -0.01F) ? (graph.scale >= 0 ? 0.01F : -0.01F) : graph.scale; }
// -------------------------------------------------------------------------------- public void SaveGraph(NavMeshGraph graph) { if (graph == null) { Debug.LogError("[NavMeshData::SaveData] Failed, graph is null"); return; } var mappedNodes = new List <NodeToUID>(); int nextId = 0; // map graph nodes to an id var nodeEnumerator = graph.NodeEnumerator; while (nodeEnumerator.MoveNext()) { NodeToUID mappedNode = new NodeToUID() { m_node = nodeEnumerator.Current, m_uid = nextId++, }; mappedNodes.Add(mappedNode); } // save node position and connections m_nodeData.Clear(); for (int i = 0; i < mappedNodes.Count; ++i) { var node = mappedNodes[i].m_node; // position & uid NavMeshNodeData nodeData = new NavMeshNodeData() { m_position = node.Data, m_uid = mappedNodes[i].m_uid, }; // connections var edgeEnumerator = node.EdgeEnumerator; while (edgeEnumerator.MoveNext()) { var connectedNode = edgeEnumerator.Current.GetOther(node); nodeData.m_connections.Add(mappedNodes.Find(n => n.m_node == connectedNode).m_uid); } m_nodeData.Add(nodeData); } }
private static Int3 InternalMove(Int3 srcLoc, Int3 delta, ref Int groundY) { Int3 num4; if ((delta.x == 0) && (delta.z == 0)) { return(delta); } Int3 end = srcLoc + delta; int edge = -1; NavMeshGraph graph = PathFindingMachine.Instance.navgationGraph as NavMeshGraph; NavMeshNode node = graph.bbTree.QueryInside(srcLoc, null); if (node == null) { NavMeshNode node2 = graph.bbTree.QueryInside(end, null); if (node2 == null) { return(Int3.zero); } else { edge = node2.EdgeIntersect(srcLoc, end); node = node2; } } MoveFromNode(node, edge, srcLoc, end, out num4); checkedNodes.Clear(); groundY = num4.y; if (!MoveAxisY) { num4.y = srcLoc.y; } return(num4 - srcLoc); }
/** Applies constrained movement from \a startPos to \a endPos. * The result is stored in \a clampedPos. * Returns the new current node */ public GraphNode ClampAlongNavmesh(Vector3 startPos, GraphNode _startNode, Vector3 endPos, out Vector3 clampedPos) { ConvexMeshNode startNode = (ConvexMeshNode)_startNode; clampedPos = endPos; Stack <ConvexMeshNode> stack = tmpStack; // Tiny stack List <ConvexMeshNode> closed = tmpClosed; // Tiny closed list stack.Clear(); closed.Clear(); Vector3 bestPos, p; float bestDist = float.PositiveInfinity; float d; ConvexMeshNode bestRef = null; // Search constraint Vector3 searchPos = (startPos + endPos) / 2; float searchRadius = Mathfx.MagnitudeXZ(startPos, endPos) / 2; // Init bestPos = startPos; stack.Push(startNode); closed.Add(startNode); // Self ref, start maker. INavmesh graph = AstarData.GetGraph(startNode) as INavmesh; if (graph == null) { //Debug.LogError ("Null graph, or the graph was no NavMeshGraph"); return(startNode); } #if ASTARDEBUG Debug.DrawLine(startPos, endPos, Color.blue); #endif while (stack.Count > 0) { // Pop front. ConvexMeshNode cur = stack.Pop(); // If target is inside the cur, stop search. if (NavMeshGraph.ContainsPoint(cur, endPos, graph.vertices)) { #if ASTARDEBUG Debug.DrawRay(endPos, Vector3.up, Color.red); #endif bestRef = cur; bestPos = endPos; break; } // Follow edges or keep track of nearest point on blocking edge. for (int i = 0, j = 2; i < 3; j = i++) { int sp = cur.GetVertexIndex(j); int sq = cur.GetVertexIndex(i); bool blocking = true; ConvexMeshNode conn = null; for (int q = 0; q < cur.connections.Length; q++) { conn = cur.connections[q] as ConvexMeshNode; if (conn == null) { continue; } for (int i2 = 0, j2 = 2; i2 < 3; j2 = i2++) { int sp2 = conn.GetVertexIndex(j2); int sq2 = conn.GetVertexIndex(i2); if ((sp2 == sp && sq2 == sq) || (sp2 == sq && sq2 == sp)) { blocking = false; break; } } if (!blocking) { break; } } //Node neiRef = cur->nei[j]; if (blocking) { // Blocked edge, calc distance. p = Mathfx.NearestPointStrictXZ((Vector3)graph.vertices[sp], (Vector3)graph.vertices[sq], endPos); #if ASTARDEBUG Debug.DrawLine((Vector3)graph.vertices[sp] + Vector3.up * 0.1F, (Vector3)graph.vertices[sq] + Vector3.up * 0.1F, Color.black); #endif d = Mathfx.MagnitudeXZ(p, endPos); if (d < bestDist) { // Update nearest distance. bestPos = p; bestDist = d; bestRef = cur; } } else { // Skip already visited. if (closed.Contains(conn)) { continue; } // Store to closed with parent for trace back. closed.Add(conn); #if ASTARDEBUG Debug.DrawLine((Vector3)cur.position, (Vector3)conn.position, Color.black); Debug.DrawLine((Vector3)graph.vertices[sp] + Vector3.up * 0.1F, (Vector3)graph.vertices[sq] + Vector3.up * 0.1F, Color.blue); #endif // Non-blocked edge, follow if within search radius. p = Mathfx.NearestPointStrictXZ((Vector3)graph.vertices[sp], (Vector3)graph.vertices[sq], searchPos); d = Mathfx.MagnitudeXZ(p, searchPos); if (d <= searchRadius) { #if ASTARDEBUG Debug.DrawLine((Vector3)searchPos - Vector3.up * 0.1F, p - Vector3.up * 0.1F, Color.cyan); #endif stack.Push(conn); } #if ASTARDEBUG else { Debug.DrawLine((Vector3)searchPos - Vector3.up * 0.1F, p - Vector3.up * 0.1F, Color.red); } #endif } } } // Trace back and store visited curgons. /* followVisited(bestRef,visited,closed); * // Store best movement position.*/ clampedPos = bestPos; // Return number of visited curs. return(bestRef); //visited.size(); }
public static Vector3 GetNextTarget(Path path, Vector3 currPosition, float offset, float pickNextWaypointMargin) { if (path.error) { return(currPosition); } Int3 currentPosition = (Int3)currPosition; int startIndex = 0; int endIndex = path.path.Length; //Int3 pos = (Int3)currentPosition; //int minDist = -1; //int minNode = -1; INavmesh navmeshGraph = AstarData.GetGraph(path.path[0]) as INavmesh; if (navmeshGraph == null) { Debug.LogError("Couldn't cast graph to the appropriate type (graph isn't a Navmesh type graph, it doesn't implement the INavmesh interface)"); return(currPosition); ///Apply (path,start,end, startIndex, endIndex, graph); } Int3[] vertices = navmeshGraph.vertices; //float minDist2 = -1; //int minNode2 = -1; //Debug.Log (meshPath.Length + " "+path.Length +" "+startIndex+" "+endIndex); /*for (int i=startIndex;i< endIndex;i++) { * MeshNode node = path.path[i] as MeshNode; * * if (node == null) { * Debug.LogWarning ("Path could not be casted to Mesh Nodes"); * return currentPosition;//return base.Apply (path,start,end, startIndex, endIndex, graph); * } * * //if (Polygon.TriangleArea2 (vertices[node.v1],vertices[node.v2],currentPosition) >= 0 || Polygon.TriangleArea2 (vertices[node.v2],vertices[node.v3],currentPosition) >= 0 || Polygon.TriangleArea2 (vertices[node.v3],vertices[node.v1],currentPosition) >= 0) { * * if (!Polygon.IsClockwise (vertices[node.v1],vertices[node.v2],pos) || !Polygon.IsClockwise (vertices[node.v2],vertices[node.v3],pos) || !Polygon.IsClockwise (vertices[node.v3],vertices[node.v1],pos)) { * * if (minDist == -1) { * float dist2 = (node.position-pos).sqrMagnitude; * if (minDist2 == -1 || dist2 < minDist2) { * minDist2 = dist2; * minNode2 = i; * } * } * continue; * } * * Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.blue); * Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.blue); * Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.blue); * * * int dist = node.position.y-pos.y; * * if (minDist == -1 || dist < minDist) { * minDist = dist; * minNode = i; * } * * }*/ MeshNode lastNode = path.path[endIndex - 1] as MeshNode; if (lastNode == null) { Debug.LogWarning("Path could not be casted to Mesh Nodes"); return(currentPosition); //return base.Apply (path,start,end, startIndex, endIndex, graph); } PathNNConstraint constraint = PathNNConstraint.Default; constraint.SetStart(lastNode); NNInfo nninfo = NavMeshGraph.GetNearestForce(path.path, vertices, currPosition, constraint); currentPosition = nninfo.clampedPosition; /*for (int i=startIndex;i< endIndex;i++) { * if (nninfo.node == path.path[i]) { * minNode = i; * } * }*/ //Node minNode = nninfo.node; /*startIndex = minNode; * if (startIndex == -1) { * startIndex = minNode2; * currentPosition = path.path[minNode2].position; * } * if (startIndex == -1) { * Debug.Log ("Couldn't find current node"); * return currentPosition; * }*/ MeshNode[] meshPath = new MeshNode[endIndex - startIndex]; for (int i = startIndex; i < endIndex; i++) { meshPath[i - startIndex] = path.path[i] as MeshNode; } //return Vector3.zero; //Vector3[] vertices = null; if (leftFunnel == null || leftFunnel.Length < meshPath.Length + 1) { leftFunnel = new Int3[meshPath.Length + 1]; } if (rightFunnel == null || rightFunnel.Length < meshPath.Length + 1) { rightFunnel = new Int3[meshPath.Length + 1]; } int leftFunnelLength = meshPath.Length + 1; //int rightFunnelLength = meshPath.Length+1; leftFunnel[0] = currentPosition; rightFunnel[0] = currentPosition; leftFunnel[meshPath.Length] = path.endPoint; rightFunnel[meshPath.Length] = path.endPoint; int lastLeftIndex = -1; int lastRightIndex = -1; for (int i = 0; i < meshPath.Length - 1; i++) { //Find the connection between the nodes MeshNode n1 = meshPath[i]; MeshNode n2 = meshPath[i + 1]; bool foundFirst = false; int first = -1; int second = -1; for (int x = 0; x < 3; x++) { //Vector3 vertice1 = vertices[n1.vertices[x]]; //n1[x] gets the vertice index for vertex number 'x' in the node. Equal to n1.GetVertexIndex (x) int vertice1 = n1[x]; for (int y = 0; y < 3; y++) { //Vector3 vertice2 = vertices[n2.vertices[y]]; int vertice2 = n2[y]; if (vertice1 == vertice2) { if (foundFirst) { second = vertice2; break; } else { first = vertice2; foundFirst = true; } } } } //Debug.DrawLine ((Vector3)vertices[first]+Vector3.up*0.1F,(Vector3)vertices[second]+Vector3.up*0.1F,Color.cyan); //Debug.Log (first+" "+second); if (first == lastLeftIndex) { leftFunnel[i + 1] = vertices[first]; rightFunnel[i + 1] = vertices[second]; lastLeftIndex = first; lastRightIndex = second; } else if (first == lastRightIndex) { leftFunnel[i + 1] = vertices[second]; rightFunnel[i + 1] = vertices[first]; lastLeftIndex = second; lastRightIndex = first; } else if (second == lastLeftIndex) { leftFunnel[i + 1] = vertices[second]; rightFunnel[i + 1] = vertices[first]; lastLeftIndex = second; lastRightIndex = first; } else { leftFunnel[i + 1] = vertices[first]; rightFunnel[i + 1] = vertices[second]; lastLeftIndex = first; lastRightIndex = second; } } //Switch the arrays so the right funnel really is on the right side (and vice versa) if (!Polygon.IsClockwise(currentPosition, leftFunnel[1], rightFunnel[1])) { Int3[] tmp = leftFunnel; leftFunnel = rightFunnel; rightFunnel = tmp; } for (int i = 1; i < leftFunnelLength - 1; i++) { //float unitWidth = 2; Int3 normal = (rightFunnel[i] - leftFunnel[i]); float magn = normal.worldMagnitude; normal /= magn; normal *= Mathf.Clamp(offset, 0, (magn / 2F)); leftFunnel[i] += normal; rightFunnel[i] -= normal; //Debug.DrawLine (rightFunnel[i],leftFunnel[i],Color.blue); } /*for (int i=0;i<path.Length-1;i++) { * Debug.DrawLine (path[i].position,path[i+1].position,Color.blue); * }*/ /*for (int i=0;i<leftFunnel.Length-1;i++) { * Debug.DrawLine (leftFunnel[i],leftFunnel[i+1],Color.red); * Debug.DrawLine (rightFunnel[i],rightFunnel[i+1],Color.magenta); * }*/ if (tmpList == null) { tmpList = new List <Vector3>(3); } List <Vector3> funnelPath = tmpList; funnelPath.Clear(); funnelPath.Add(currentPosition); Int3 portalApex = currentPosition; Int3 portalLeft = leftFunnel[0]; Int3 portalRight = rightFunnel[0]; int apexIndex = 0; int rightIndex = 0; int leftIndex = 0; //yield return 0; for (int i = 1; i < leftFunnelLength; i++) { Int3 left = leftFunnel[i]; Int3 right = rightFunnel[i]; /*Debug.DrawLine (portalApex,portalLeft,Color.red); * Debug.DrawLine (portalApex,portalRight,Color.yellow); * Debug.DrawLine (portalApex,left,Color.cyan); * Debug.DrawLine (portalApex,right,Color.cyan);*/ if (Polygon.TriangleArea2(portalApex, portalRight, right) >= 0) { if (portalApex == portalRight || Polygon.TriangleArea2(portalApex, portalLeft, right) <= 0) { portalRight = right; rightIndex = i; } else { funnelPath.Add((Vector3)portalLeft); //if (funnelPath.Count > 3) //break; portalApex = portalLeft; apexIndex = leftIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; //yield return 0; continue; } } if (Polygon.TriangleArea2(portalApex, portalLeft, left) <= 0) { if (portalApex == portalLeft || Polygon.TriangleArea2(portalApex, portalRight, left) >= 0) { portalLeft = left; leftIndex = i; } else { funnelPath.Add((Vector3)portalRight); //if (funnelPath.Count > 3) //break; portalApex = portalRight; apexIndex = rightIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; //yield return 0; continue; } } //yield return 0; } //yield return 0; funnelPath.Add(path.endPoint); Vector3[] p = funnelPath.ToArray(); if (p.Length <= 1) { return(currentPosition); } for (int i = 1; i < p.Length - 1; i++) { Vector3 closest = Mathfx.NearestPointStrict(p[i], p[i + 1], currentPosition); if ((closest - (Vector3)currentPosition).sqrMagnitude < pickNextWaypointMargin * pickNextWaypointMargin) { continue; } else { return(p[i]); } } return(p[p.Length - 1]); }
// Token: 0x0600001A RID: 26 RVA: 0x00002B84 File Offset: 0x00000F84 public GraphNode ClampAlongNavmesh(Vector3 startPos, GraphNode _startNode, Vector3 endPos, out Vector3 clampedPos) { TriangleMeshNode triangleMeshNode = (TriangleMeshNode)_startNode; clampedPos = endPos; Stack <TriangleMeshNode> stack = this.tmpStack; List <TriangleMeshNode> list = this.tmpClosed; stack.Clear(); list.Clear(); float num = float.PositiveInfinity; TriangleMeshNode result = null; Vector3 vector = (startPos + endPos) / 2f; float num2 = AstarMath.MagnitudeXZ(startPos, endPos) / 2f; Vector3 vector2 = startPos; stack.Push(triangleMeshNode); list.Add(triangleMeshNode); INavmesh navmesh = AstarData.GetGraph(triangleMeshNode) as INavmesh; if (navmesh == null) { return(triangleMeshNode); } while (stack.Count > 0) { TriangleMeshNode triangleMeshNode2 = stack.Pop(); int tileIndex = ((RecastGraph)navmesh).GetTileIndex(triangleMeshNode2.GetVertexIndex(0)); Int3[] verts = ((RecastGraph)navmesh).GetTiles()[tileIndex].verts; int vertexArrayIndex = triangleMeshNode2.GetVertexArrayIndex(triangleMeshNode2.v0); int vertexArrayIndex2 = triangleMeshNode2.GetVertexArrayIndex(triangleMeshNode2.v1); int vertexArrayIndex3 = triangleMeshNode2.GetVertexArrayIndex(triangleMeshNode2.v2); if (NavMeshGraph.ContainsPoint(vertexArrayIndex, vertexArrayIndex2, vertexArrayIndex3, endPos, verts)) { result = triangleMeshNode2; vector2 = endPos; break; } int i = 0; int i2 = 2; while (i < 3) { int vertexIndex = triangleMeshNode2.GetVertexIndex(i2); int vertexIndex2 = triangleMeshNode2.GetVertexIndex(i); bool flag = true; TriangleMeshNode triangleMeshNode3 = null; for (int j = 0; j < triangleMeshNode2.connections.Length; j++) { triangleMeshNode3 = (triangleMeshNode2.connections[j] as TriangleMeshNode); if (triangleMeshNode3 != null) { int k = 0; int i3 = 2; while (k < 3) { int vertexIndex3 = triangleMeshNode3.GetVertexIndex(i3); int vertexIndex4 = triangleMeshNode3.GetVertexIndex(k); if ((vertexIndex3 == vertexIndex && vertexIndex4 == vertexIndex2) || (vertexIndex3 == vertexIndex2 && vertexIndex4 == vertexIndex)) { flag = false; break; } i3 = k++; } if (!flag) { break; } } } if (flag) { Vector3 vector3 = AstarMath.NearestPointStrictXZ((Vector3)verts[vertexIndex], (Vector3)verts[vertexIndex2], endPos); float num3 = AstarMath.MagnitudeXZ(vector3, endPos); if (num3 < num) { vector2 = vector3; num = num3; result = triangleMeshNode2; } } else if (!list.Contains(triangleMeshNode3)) { list.Add(triangleMeshNode3); Vector3 vector3 = AstarMath.NearestPointStrictXZ((Vector3)verts[vertexIndex], (Vector3)verts[vertexIndex2], vector); float num3 = AstarMath.MagnitudeXZ(vector3, vector); if (num3 <= num2) { stack.Push(triangleMeshNode3); } } i2 = i++; } } clampedPos = vector2; return(result); }
private IEnumerator UpdateGraphRoutine(NavMeshGraph graph) { updateInProgress = true; pathing.AddWorkItem(() => { UnstitchFromNeighbors(graph); }); pathing.FlushWorkItems(); while (pathing.IsAnyWorkItemInProgress) { yield return(null); } if (toRemove.Contains(graph)) { pathing.data.RemoveGraph(graph); toRemove.Remove(graph); } else { while (pathing.isScanning) { yield return(null); } pathing.Scan(graph); while (pathing.isScanning) { yield return(null); } pathing.AddWorkItem(() => { StitchToNeighbors(graph); }); pathing.FlushWorkItems(); while (pathing.IsAnyWorkItemInProgress) { yield return(null); } if (!lastUpdate.ContainsKey(graph)) { lastUpdate.Add(graph, Time.time); } else { lastUpdate[graph] = Time.time; } } updateInProgress = false; if (updateQueue.Count > 0) { StartCoroutine(UpdateGraphRoutine(updateQueue.Dequeue())); } }
private void UnstitchFromNeighbors(NavMeshGraph myGraph) { myGraph.GetNodes(node => RemoveOffGraphConnections(node)); }