/// <summary> /// Instantiates a GameObject showing connections between <see cref="RoadLatticeNode"/>s without /// distinguishing disjoint partitions of the road graph. /// </summary> /// <param name="lattice">The lattice from which to generate a GameObject</param> /// <param name="indicateNodes">Whether to add markers at each node</param> /// <param name="material">The material to apply to the generated mesh</param> /// <returns>The GameObject representation of the supplied lattice</returns> private static GameObject MakeUnpartitionedLatticeDebugGameObject( RoadLattice lattice, bool indicateNodes, Material material) { GameObject latticeParent = new GameObject(); latticeParent.name = "Road Lattice"; List <Vector2> vertices = new List <Vector2>(); List <RoadLatticeNode> nodes = lattice.GetNodes(); HashSet <RoadLatticeNode> processed = new HashSet <RoadLatticeNode>(); foreach (RoadLatticeNode node in nodes) { if (processed.Contains(node)) { continue; } if (indicateNodes) { MakeRoadLatticeNodeIndicator(node, latticeParent); } processed.Add(node); foreach (RoadLatticeNode neighbor in node.Neighbors) { vertices.Add(node.Location); vertices.Add(neighbor.Location); } } MakeSublatticeMeshes(latticeParent, vertices, material); return(latticeParent); }
protected void PathTo(Vector3 endPosition) { // Snap start/end positions to road lattice nodes RoadLatticeNode startNode = BaseMapLoader.MapsService.RoadLattice.SnapToNode(transform.position); RoadLatticeNode endNode = BaseMapLoader.MapsService.RoadLattice.SnapToNode(endPosition); // Find path between start/end nodes PathToDestination = RoadLattice.UncheckedFindPath(startNode, endNode, PathSearchLimit); // Reset our pathfinding instructions - waypoint at index 0 is our start position WaypointIndex = 0; if (PathToDestination != null && PathToDestination.Count > 0) { // Init navigation details - our next target is the waypoint after the start position CurrentTargetPosition = new Vector3( PathToDestination[WaypointIndex].Location.x, transform.position.y, PathToDestination[WaypointIndex].Location.y); IsMoving = true; } else { IsMoving = false; } DisplayRoute(PathToDestination); }
/// <summary> /// Receives two game objects, snaps them to the current road lattice, and displays the shortest /// path between them. /// </summary> /// <remarks> /// Can be attached as a Unity event handler to the /// <see cref="RoadLatticePathFindingObjectMover.UpdatedPositions"/> UnityEvent. /// </remarks> /// <param name="start">The path start object.</param> /// <param name="end">The path end object.</param> public void CreatePathBetweenObjects(GameObject start, GameObject end) { if (PathDisplay != null) { Destroy(PathDisplay); } RoadLatticeNode startNode = MapsService.RoadLattice.SnapToNode(start.transform.position); RoadLatticeNode endNode = MapsService.RoadLattice.SnapToNode(end.transform.position); start.transform.position = new Vector3(startNode.Location.x, 0, startNode.Location.y); end.transform.position = new Vector3(endNode.Location.x, 0, endNode.Location.y); List <RoadLatticeNode> path = RoadLattice.UncheckedFindPath(startNode, endNode, PathSearchLimit); if (path == null) { Debug.LogFormat("No path found!"); } else { PathDisplay = MakeRouteDisplay(path); PathDisplay.transform.Translate(Vector3.up * PathDisplayY); } }
/// <summary> /// Instantiates a GameObject showing connections between <see cref="RoadLatticeNode"/>s, /// creating a separate mesh for each road priority, and assigning materials based on priority. /// </summary> /// <param name="lattice">The lattice from which to generate a GameObject</param> /// <param name="materials">The materials to apply to the generated meshes</param> /// <param name="indicateNodes">Whether to add markers at each node</param> /// <returns>The GameObject representation of the supplied lattice</returns> public static GameObject MakeAttributedLatticeDebugGameObject( RoadLattice lattice, Material[] materials, bool indicateNodes) { GameObject latticeParent = new GameObject(); latticeParent.name = "Road Lattice"; // One set of mesh vertices per road priority, plus one for the default. List <Vector2>[] vertices = new List <Vector2> [RoadPriorities.Length + 1]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new List <Vector2>(); } List <RoadLatticeNode> nodes = lattice.GetNodes(); HashSet <RoadLatticeNode> processed = new HashSet <RoadLatticeNode>(); foreach (RoadLatticeNode node in nodes) { if (indicateNodes) { MakeRoadLatticeNodeIndicator(node, latticeParent); } foreach (RoadLatticeEdge edge in node.Edges) { if (processed.Contains(edge.Target)) { continue; } // Map the road priority to the supplied materials using the RoadPriorities array. int index = (Array.IndexOf(RoadPriorities, edge.Segment.Metadata.Usage) + 1) % vertices.Length; vertices[index].Add(node.Location); vertices[index].Add(edge.Target.Location); } processed.Add(node); } for (int i = 0; i < vertices.Length; i++) { MakeSublatticeMeshes(latticeParent, vertices[i], materials[i % materials.Length]); } return(latticeParent); }
/// <summary> /// Instantiates a GameObject showing connections between <see cref="RoadLatticeNode"/> objects. /// </summary> /// <param name="lattice">The lattice from which to generate a GameObject</param> /// <param name="materials"> /// The material(s) to apply to the created RoadLattice object</param> /// <param name="indicateNodes">Whether to add markers at each node</param> /// <param name="showPartitioning"> /// Whether to create separate debug objects for each independent, contiguous sub-lattice /// </param> /// <returns>The GameObject representation of the supplied lattice</returns> public static GameObject MakeRoadLatticeDebugGameObject( RoadLattice lattice, Material[] materials, bool indicateNodes, bool showPartitioning) { if (materials == null || materials.Length == 0) { materials = new Material[] { null }; } if (!showPartitioning) { return(MakeUnpartitionedLatticeDebugGameObject(lattice, indicateNodes, materials[0])); } else { return(MakePartitionedRoadLatticeDebugGameObject(lattice, indicateNodes, materials)); } }
/// <summary> /// Instantiates a GameObject showing connections between <see cref="RoadLatticeNode"/>s using /// materials to distinguish disjoint partitions of the road graph. /// </summary> /// <param name="lattice">The lattice from which to generate a GameObject</param> /// <param name="indicateNodes">Whether to add markers at each node</param> /// <param name="materials">The materials to apply to the disjoint sub-lattices</param> /// <returns>The GameObject representation of the supplied lattice</returns> private static GameObject MakePartitionedRoadLatticeDebugGameObject( RoadLattice lattice, bool indicateNodes, Material[] materials) { // A list for collecting road segment end point locations. List <Vector2> vertices = new List <Vector2>(); // A set of nodes with connections to other nodes that have all been converted into geometry. HashSet <RoadLatticeNode> processed = new HashSet <RoadLatticeNode>(); int materialIndex = 0; GameObject latticeParent = new GameObject(); latticeParent.name = "Road Lattice Parent"; List <RoadLatticeNode> nodes = lattice.GetNodes(); foreach (RoadLatticeNode node in nodes) { // Skip this node if it has already had all its connections turned into geometry, otherwise // use it as the starting node for a new disjoint sub-lattice representation. if (processed.Contains(node)) { continue; } vertices.Clear(); // A set of nodes reachable from the set of nodes that have been processed so far. Note: this // list may contain nodes that have already been processed if such ndoes are reachable from // more than one neighbouring node. Stack <RoadLatticeNode> reachableNodes = new Stack <RoadLatticeNode>(); reachableNodes.Push(node); // Keep processing nodes til we have visited all reachable nodes. while (reachableNodes.Count > 0) { RoadLatticeNode source = reachableNodes.Pop(); // Skip nodes we have previously processed by reaching them through an alternative path. if (processed.Contains(source)) { continue; } if (indicateNodes) { MakeRoadLatticeNodeIndicator(source, latticeParent); } // Mark this node as processed, add segments for all its connections, and add all its // neighbours to the reachable set. processed.Add(source); foreach (RoadLatticeNode neighbor in source.Neighbors) { if (!processed.Contains(neighbor)) { vertices.Add(source.Location); vertices.Add(neighbor.Location); reachableNodes.Push(neighbor); } } } GameObject go = new GameObject(); go.name = "Road Lattice"; MakeSublatticeMeshes(go, vertices, materials[materialIndex]); materialIndex = (materialIndex + 1) % materials.Length; go.transform.parent = latticeParent.transform; } return(latticeParent); }