//Create pathNode for sparse graph public void ConnectGraphs(int GraphIDA, int GraphNodeA, int GraphIDB, int GraphNodeB) { sparseGraph.AddNodes(1); pathNode linker = sparseGraph.GetNodeList()[sparseGraph.NodeCount - 1]; //Place linker node over doorway linker.position = Graphs[GraphIDA].GetNodeList()[GraphNodeA].position; //Link A to B Graphs[GraphIDA].LinkGraph(Graphs[GraphIDB], GraphNodeA, linker); //Link B to A Graphs[GraphIDB].LinkGraph(Graphs[GraphIDA], GraphNodeB, linker); }
void OnEnable() { _target = (SimpleAIGraphContainer)target; Graph = _target.GetGraph(); if (Graph == null) { Graph = new GraphSimple(); } //Ensure that the root node is part of the path if (Graph.NodeCount < 1) { Graph.AddNodes(1); Graph.GetNodeList()[0].position = _target.transform.position; } }
//Not meant for real-time use public void ConstructGraph() { if (meshGraph == null) { Debug.Log("No mesh to operate on! Please set meshGraph before calling this function"); return; } //Create a sampler Gameobject to perform raycasts to neighboring nodes Sampler = new GameObject("Sampler"); List <int> neighbors; List <int> DeadVertices = new List <int>(); List <pathNode> DeadNodes = new List <pathNode>(); simpleGraph = new GraphSimple(); simpleGraph.AddNodes(meshGraph.vertexCount); float dist = 0; for (int i = 0; i < meshGraph.vertexCount; i++) { //if(DeadVertices.Contains(i)) //continue; neighbors = GetNeighbors(i); pathNode currentNode = simpleGraph.graph[i]; currentNode.position = transform.TransformPoint(meshGraph.vertices[i]); for (int j = 0; j < neighbors.Count; j++) { dist = Vector3.Distance(transform.TransformPoint(meshGraph.vertices[i]), transform.TransformPoint(meshGraph.vertices[neighbors[j]])); currentNode.neighbors.Add(simpleGraph.graph[neighbors[j]]); currentNode.weight.Add(dist); Sampler.transform.position = transform.TransformPoint(meshGraph.vertices[i]); if (Physics.Raycast(Sampler.transform.position, Vector3.Normalize(meshGraph.vertices[neighbors[j]] - meshGraph.vertices[i]), dist)) { if (!DeadVertices.Contains(neighbors[j])) { DeadVertices.Add(neighbors[j]); DeadNodes.Add(simpleGraph.graph[neighbors[j]]); break; } } } //Debug.Log(i); } foreach (pathNode node in DeadNodes) { simpleGraph.DeleteNode(node.ID); } //Rebuild mesh NavMeshGenerator.RemoveTriangles(meshGraph, DeadVertices); }
//Faster Method public void BuildPlaneGraph(float width, float height, int segments) { this.width = width; this.height = height; simpleGraph = new GraphSimple(); List <int> Neighbors = new List <int>(); List <float> Weights = new List <float>(); float deltaHeight = height / segments; float deltaWidth = width / segments; //transform.TransformPoint(new Vector3(j*(width/segments)-width/2, 0, i*(height/segments)-height/2)); simpleGraph.AddNodes((segments + 1) * (segments + 1)); List <pathNode> DeadNodes = new List <pathNode>(); List <int> DeadVerts = new List <int>(); pathNode currentNode; for (int i = 0; i <= segments; i++) { for (int j = 0; j <= segments; j++) { currentNode = simpleGraph.GetNodeList()[i * (segments + 1) + j]; currentNode.position = transform.TransformPoint(new Vector3(j * (deltaWidth) - width / 2, 0, i * (deltaHeight) - height / 2)); //RaycastHit hit; //if (Physics.Raycast(currentNode.position, -Vector3.up, out hit)) //{ // currentNode.position=transform.TransformPoint(new Vector3(j*(deltaWidth)-width/2, hit.point.y, i*(deltaHeight)-height/2)); //} Neighbors.Clear(); Weights.Clear(); //Debug.Log ("Node #"+(i*(segments+1)+j)); //Up and Down if (i > 0) { Neighbors.Add(((i - 1) * (segments + 1) + (j))); Weights.Add(deltaHeight); //Debug.Log ("Down"); } if (i < segments) { Neighbors.Add(((i + 1) * (segments + 1) + (j))); Weights.Add(deltaHeight); //Debug.Log ("Up"); } //Left and Right if (j > 0) { Neighbors.Add(((i) * (segments + 1) + (j - 1))); Weights.Add(deltaWidth); //Debug.Log ("Left"); } if (j < segments) { Neighbors.Add(((i) * (segments + 1) + (j + 1))); Weights.Add(deltaWidth); //Debug.Log ("Right"); } //Top-left to Bottom-right Diagonal if (i > 0 && j > 0) { Neighbors.Add((i - 1) * (segments + 1) + (j - 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Bottom Left"); } if (i < segments && j < segments) { Neighbors.Add((i + 1) * (segments + 1) + (j + 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Top right"); } //Top-right to Bottom-left Diagonal if ((i < segments) && j > 0) { Neighbors.Add(((i + 1) * (segments + 1) + (j - 1))); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Top left"); } if (i > 0 && j < segments) { Neighbors.Add((i - 1) * (segments + 1) + (j + 1)); Weights.Add(Mathf.Sqrt(deltaWidth * deltaWidth + deltaHeight * deltaHeight)); //Debug.Log ("Bottom Right"); } int index = 0; foreach (int Neighbor in Neighbors) { //Debug.Log (Neighbor); pathNode neighbor = simpleGraph.GetNodeList()[Neighbor]; currentNode.neighbors.Add(neighbor); currentNode.weight.Add(Weights[index]); index++; } //Debug.Log(i); } } foreach (pathNode node in simpleGraph.GetNodeList()) { node.dist = 0; } //Scan physics graph foreach (pathNode node in simpleGraph.GetNodeList()) { //Debug.Log (node.neighbors.Count); for (int i = 0; i < node.neighbors.Count; i++) { pathNode Neighbor = node.neighbors[i]; //Debug.Log ("Ray cast from "+node.position+" to "+Neighbor.position+" with a distance of "+Vector3.Distance(Neighbor.position,node.position)); //Debug.Log ("Node #"+node.ID+" Hit toward: "+Neighbor.ID); if (Physics.Raycast(node.position, Vector3.Normalize(Neighbor.position - node.position), Vector3.Distance(Neighbor.position, node.position))) { //Debug.DrawLine(Neighbor.position,node.position); if (!Physics.Raycast(node.position, Vector3.Normalize(node.position - Neighbor.position), Vector3.Distance(Neighbor.position, node.position))) { if (DeadVerts.Contains(Neighbor.ID)) { DeadNodes.Add(Neighbor); DeadVerts.Add(Neighbor.ID); } } //removeCount++; node.neighbors.RemoveAt(i); node.weight.RemoveAt(i); i--; Neighbor.dist += 1; } } } //Dead Node Removal for (int i = 0; i < DeadNodes.Count; i++) { //Debug.Log (DeadNodes[i]); simpleGraph.DeleteNode(DeadNodes[i].ID); } //Filter nodes Remove count for (int i = 0; i < simpleGraph.NodeCount; i++) { pathNode node = simpleGraph.GetNodeList()[i]; //Debug.Log("Hit count: "+node.dist); if (node.dist >= 3) { simpleGraph.DeleteNode(node.ID); i--; } } for (int i = 0; i < simpleGraph.NodeCount; i++) { pathNode node = simpleGraph.GetNodeList()[i]; if (node.neighbors.Count < 3) { simpleGraph.DeleteNode(node.ID); } } }
void Update() { if (CurrentDistanceNodeIDInt != DistanceNodeIDInt) { CurrentDistanceNodeIDInt = DistanceNodeIDInt; GetDistances(); } if (CurrentPathRootNodeIDInt != PathRootNodeIDInt || CurrentPathEndNodeIDInt != PathEndNodeIDInt) { CurrentPathRootNodeIDInt = PathRootNodeIDInt; CurrentPathEndNodeIDInt = PathEndNodeIDInt; GetPaths(); } if (cam == null) { cam = GameObject.FindGameObjectWithTag("MainCamera").GetComponent(typeof(Camera)) as Camera; } if (!GUIMouseOver()) { GetPoint(); if (PlaceNodes && Input.GetMouseButtonDown(0)) { Nodes.Add(GameObject.CreatePrimitive(PrimitiveType.Sphere)); Nodes[Nodes.Count - 1].transform.position = NodePoint; Nodes[Nodes.Count - 1].name = (Nodes.Count - 1).ToString(); Nodes[Nodes.Count - 1].layer = 13; Labels.Add(Instantiate(Textmesh) as GameObject); Labels[Labels.Count - 1].transform.position = (NodePoint); tempMesh = Labels[Labels.Count - 1].GetComponent(typeof(TextMesh)) as TextMesh; tempMesh.text = (Labels.Count - 1).ToString(); tempMesh.color = Color.white; testGraph.AddNodes(1); GetDistances(); } if (ConnectNodes) { if (Input.GetMouseButtonDown(0)) { A = IDPoint; } if (ConnectNodes && Input.GetMouseButtonUp(0)) { B = IDPoint; } if (A == B) { A = -1; B = -1; } } if (A >= 0 && B >= 0 && B != A) { testGraph.ConnectNodes(A, B, weightF); bool copy = false; int index = 0; foreach (GameObject obj in Lines) { if (obj.name.Contains(A + " to " + B + " Connection") || obj.name.Contains(B + " to " + A + " Connection")) { copy = true; break; } index++; copy = false; } if (copy == false) { Lines.Add(new GameObject(A + " to " + B + " Connection")); Text.Add(Instantiate(Textmesh) as GameObject); LineRenderer tempLine = Lines[Lines.Count - 1].AddComponent(typeof(LineRenderer)) as LineRenderer; tempLine.GetComponent <Renderer>().material = LineBlack; tempLine.SetWidth(0.3f, 0.3f); tempLine.SetPosition(0, Nodes[A].transform.position); tempLine.SetPosition(1, Nodes[B].transform.position); Text[Text.Count - 1].transform.position = (Nodes[A].transform.position + Nodes[B].transform.position) / 2; tempMesh = Text[Text.Count - 1].GetComponent(typeof(TextMesh)) as TextMesh; tempMesh.text = weightF.ToString(); tempMesh.color = Color.red; GetDistances(); } else { tempMesh = Text[index].GetComponent(typeof(TextMesh)) as TextMesh; tempMesh.text = weightF.ToString(); GetDistances(); } GetPaths(); Debug.Log("Connect:" + A + " to " + B); A = -1; B = -1; } } }
public override void OnInspectorGUI() { GraphContainer = _target.transform.parent.GetComponent(typeof(SimpleAIGraphContainer)) as SimpleAIGraphContainer; if (_target.Node != Graph.GetNodeList()[_target.Node.ID]) { _target.Node = Graph.GetNodeList()[_target.Node.ID]; } GUILayout.BeginVertical(); if (_target.Node != null) { GUILayout.Label("Node Information", EditorStyles.boldLabel); GUILayout.Label("ID: " + _target.Node.ID); GUILayout.BeginHorizontal(); GUILayout.Label("Passthrough?: "); if (_target.Node.passThrough) { if (GUILayout.Button("True")) { _target.Node.passThrough = false; } } else { if (GUILayout.Button("False")) { _target.Node.passThrough = true; } } GUILayout.EndHorizontal(); GUILayout.Label("Position: " + _target.Node.position); GUILayout.Label("Neighbors: ", EditorStyles.boldLabel); for (int i = 0; i < _target.Node.neighbors.Count; i++) { GUILayout.Label("Node " + _target.Node.neighbors[i].ID); } } _target.Node.position = _target.transform.position; if (GUILayout.Button("Add Node") && GraphContainer != null) { Graph.AddNodes(1); Graph.GetNodeList()[GraphContainer.GetGraph().NodeCount - 1].position = _target.transform.position + new Vector3(1, 0, 0); Graph.ConnectNodes(_target.Node.ID, Graph.NodeCount - 1, 1); Graph.ConnectNodes(Graph.NodeCount - 1, _target.Node.ID, 1); GameObject tempObj = new GameObject(""); tempObj.transform.position = _target.transform.position + new Vector3(1, 0, 0); pathNodeContainer tempNode = tempObj.AddComponent(typeof(pathNodeContainer)) as pathNodeContainer; tempNode.Node = Graph.GetNodeList()[Graph.NodeCount - 1]; tempNode.GenerateName(); tempObj.transform.parent = GraphContainer.transform; } if (GUILayout.Button("Merge Closest Node") && GraphContainer != null) { int closestID = _target.Node.ID; float minDist = Mathf.Infinity; for (int i = 0; i < Graph.NodeCount; i++) { float dist = Vector3.Distance(Graph.GetNodeList()[i].position, _target.transform.position); if (dist < minDist && Graph.GetNodeList()[i].ID != _target.Node.ID) { minDist = dist; closestID = Graph.GetNodeList()[i].ID; } } if (closestID != _target.Node.ID) { if (EditorUtility.DisplayDialog("Merge nodes?", "The closest node is node " + closestID + ", would you like to merge these nodes together?", "Merge", "Cancel")) { GraphContainer.MergeNodes(_target.Node.ID, closestID); destroyMe = true; } } } if (GUILayout.Button("Delete Node") && GraphContainer != null) { if (EditorUtility.DisplayDialog("Delete Selected Node?", "Are you sure you want to delete node " + _target.Node.ID + "?", "Delete", "Cancel")) { GraphContainer.DeleteNode(_target.Node.ID); destroyMe = true; } } GUILayout.EndVertical(); if (destroyMe) { DestroyImmediate(_target.gameObject); } }