public void OnInspectorGUI() { EditorGUILayout.Space(); EditorGUILayout.LabelField("Road Settings", GUIStyles.GroupTitleStyle); #if EASY_ROADS GUILayout.BeginHorizontal(); { // show error color in case there's no container if (erRoad == null) { editor.SetErrorBackgroundColor(); } EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(road, new GUIContent("Road", "The Easy Roads road which will get the Biome Mask Area's nodes transferred to")); if (EditorGUI.EndChangeCheck()) { if (road.objectReferenceValue != null) { erRoad = erRoadNetwork.GetRoadByGameObject(road.objectReferenceValue as GameObject); } } // default color in case error color was set editor.SetDefaultBackgroundColor(); } GUILayout.EndHorizontal(); // consistency check for EasyRoads road GUILayout.BeginHorizontal(); if (erRoad == null) { EditorGUILayout.HelpBox("Easy Roads GameObject of type Road required", MessageType.Error); } GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(smoothEnabled, new GUIContent("Smooth", "Perform smoothing on the polygon")); EditorGUILayout.PropertyField(closedTrack, new GUIContent("Closed Track", "Set the Closed Track setting of the road")); EditorGUILayout.PropertyField(minDistance, new GUIContent("Min. Node Distance", "Minimum distance between nodes. Use this to remove close curve jitter")); EditorGUILayout.PropertyField(autoPlaceGameObject, new GUIContent("Auto Placement", "Automatically place a GameObject on the road")); if (autoPlaceGameObject.boolValue) { if (placementGameObject.objectReferenceValue == null) { editor.SetErrorBackgroundColor(); } EditorGUILayout.PropertyField(placementGameObject, new GUIContent("Placement GameObject", "The GameObject to place automatically.")); editor.SetDefaultBackgroundColor(); } #else EditorGUILayout.HelpBox("Requires Easy Roads installed and 'EASY_ROADS' Scripting Define Symbol", MessageType.Error); #endif }
// Receive the JSON results from the Mapzen download // Parse the JSON to create road objects using EasyRoads3D public void ReceiveDownloadResults(string results) { var json = JSON.Parse(results); JSONArray roadFeatures = json ["roads"] ["features"].AsArray; currentThreadRoads = new List <ERRoad> (); for (int i = 0; i < roadFeatures.Count; i++) { string type = roadFeatures [i] ["geometry"] ["type"].Value; string kindOfRoad = roadFeatures [i] ["properties"] ["kind"].Value; string nameOfRoad = roadFeatures [i] ["properties"] ["name"].Value; if (kindOfRoad != "path") { if (type == "LineString") { JSONArray coordinates = roadFeatures [i] ["geometry"] ["coordinates"].AsArray; Vector3[] roadMarkers = parseLineString(coordinates); ERRoad road = roadNetwork.CreateRoad(nameOfRoad, roadType, roadMarkers); addRoad(road); } else if (type == "MultiLineString") { JSONArray coordinates = roadFeatures [i] ["geometry"] ["coordinates"].AsArray; for (int j = 0; j < coordinates.Count; j++) { JSONArray coords = coordinates [j].AsArray; Vector3[] roadMarkers = parseLineString(coords); ERRoad road = roadNetwork.CreateRoad(nameOfRoad, roadType, roadMarkers); addRoad(road); } } } } }
public override void OnInspectorGUI() { rNet = target as RouteNet; base.OnInspectorGUI(); EditorGUI.BeginChangeCheck(); if (GUILayout.Button("BuildAllRoute")) { Undo.RecordObject(target, "BuildAllRoute"); ERRoadNetwork net = new ERRoadNetwork(); foreach (var r in rNet.allRoutes) { Debug.Log("Road Name : " + r.__roadName + " Points Count " + r.positions.Count); markers = net.GetRoadByName(r.__roadName); if (markers == null) { Debug.LogError("NO SUCH ROAD.....CANCELED......"); continue; } r.resolution = 50; Vector3[] arr = markers.GetSplinePointsCenter(); r.positions = new List <Vector3>(arr); for (int i = 0; i < r.positions.Count; i++) { //Debug.Log(r.positions[i]); } } EditorUtility.SetDirty(target); } }
/// <summary> /// Methode zum Fahren des Autos (Simulation). /// </summary> public void SimulateCar() { // Die Collider des Autos holen Collider[] colliders = Physics.OverlapBox(cameraCar.gameObject.transform.position, (cameraCar.gameObject.transform.localScale / 5f), cameraCar.gameObject.transform.rotation); List <Collider> carColliders = new List <Collider>(); ERRoad road = null; foreach (Collider collider in colliders) { if (collider.tag == "Street") { road = network.GetRoadByName(collider.name); } if (collider.tag == "Car") { carColliders.Add(collider); } } Vector3 heading = new Vector3(0, 0, 1); if (road != null) { // Hole den letzten Punkt der Strecke Vector3[] markers = road.GetMarkerPositions(); Vector3 lastMarker = markers.Last(); // Die richtige Rotation ausrechnen heading = (lastMarker - markers[markers.Length - 2]).normalized; heading.y = 0; CustomEasyRoad customEasy = null; foreach (CustomEasyRoad customEasyRoad in customEasyRoads) { if (customEasyRoad.Road.GetName() == road.GetName()) { customEasy = customEasyRoad; break; } } //Tuple<Vector3, Vector3> markers = customEasy.GetIncludingMarkers(cameraCar.gameObject.transform.position); //heading = (markers.Second - markers.First).normalized; //heading.y = 0; } // Geschwindigkeit setzen Rigidbody rigidbody = cameraCar.GetComponent <Rigidbody>(); cameraCar.transform.Translate(Vector3.forward * (carSpeed / 3.6f) * Time.deltaTime); //cameraCar.transform.rotation.SetLookRotation(heading); cameraCar.transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(heading), 2.5f * Time.deltaTime); // Die Autos im Weg entfernen foreach (Collider collider in carColliders) { Destroy(collider.gameObject); } }
/// <summary> /// Methode zum Erstellen einer CustomEasyRoad. /// </summary> /// <param name="car">Das Gameobject des Autos.</param> /// <param name="road">Die Straße.</param> /// <param name="minCars">Die Mindestanzahl von Autos auf dem Streckenpart.</param> /// <param name="maxCars">Die Maximalanzahl von Autos auf dem Streckenpart.</param> /// <param name="numberOfTracks">Die Anzahl der Spuren.</param> public CustomEasyRoad(GameObject car, ERRoad road, int minCars, int maxCars, int numberOfTracks) { road.SetTag("Street"); this.Road = road; this.CarsOnLanes = new List <Tuple <GameObject, int> >(); this.CarsPerLane = new Dictionary <int, List <GameObject> >(); for (int i = 0; i < numberOfTracks; i++) { List <GameObject> carsOnLane = new List <GameObject>(); CarsPerLane.Add(i, carsOnLane); } Vector3[] markers = road.GetSplinePointsCenter(); Vector3[] markersR = road.GetSplinePointsRightSide(); Vector3[] markersL = road.GetSplinePointsLeftSide(); int carCount = Random.Range(minCars, maxCars); if (carCount > 0) { int increment = markers.Length / carCount; Vector3 look = Vector3.zero; GameObject newCar = null; for (int i = 0; i < markers.Length; i += increment) { // Die Spur bestimmen int lane = Random.Range(0, numberOfTracks); Vector3[] directionMarkers = null; // Die Richtung des Autos/Lane holen und setzen if (lane < (numberOfTracks / 2)) { directionMarkers = markersL; look = (markers[Mathf.Max(0, i - 1)] - markers[Mathf.Min(markers.Length - 1, i + 1)]); } else { directionMarkers = markersR; look = (markers[Mathf.Min(markers.Length - 1, i + 1)] - markers[Mathf.Max(0, i - 1)]); } // Den RoadSlerp holen float roadSlerp = RoadUtils.GetRoadSlerpByLane(numberOfTracks, lane); // Das Car mit der Richtung und der Spur spawnen newCar = GameObject.Instantiate(car, Vector3.Slerp(markers[i], directionMarkers[i], roadSlerp) + new Vector3(0, 1, 0), Quaternion.LookRotation(look)); // Das Auto den Listen hinzufügen this.AddToIndexOnLane(lane, newCar); CarsOnLanes.Add(new Tuple <GameObject, int>(newCar, numberOfTracks - lane - 1)); } } }
public Vector3 GetPosition(ERRoad road, float distance) { //if (road.roadScript.distances != null && road.roadScript.distances.Count < 3) //{ // Debug.Log(road.roadScript.transform.name); road.roadScript.distances.Clear(); road.SetDistances(); //} Vector3 result = Vector3.zero; int prevIndex = 0, nextIndex = 0; float prevIndexDistance = 0f, nextIndexDistance = 0f; if (road.roadScript.distances.Count < 2) { return(result); } if (distance < road.roadScript.distances[0]) { return(road.roadScript.soSplinePoints[0]); } if (road.roadScript.distances.Count == 2) { prevIndex = 0; nextIndex = 1; } else if (distance > road.roadScript.distances[road.roadScript.distances.Count - 1]) { return(road.roadScript.soSplinePoints[road.roadScript.distances.Count - 1]); } if (road.roadScript.distances.Count > 2) { for (int i = 0; i < road.roadScript.distances.Count - 1; i++) { if (road.roadScript.distances[i] <= distance && road.roadScript.distances[i + 1] >= distance) { prevIndex = i; nextIndex = i + 1; } } } prevIndexDistance = road.roadScript.distances[prevIndex]; nextIndexDistance = road.roadScript.distances[nextIndex]; result = Vector3.Lerp(road.roadScript.soSplinePoints[prevIndex], road.roadScript.soSplinePoints[nextIndex], ((distance - prevIndexDistance) / (nextIndexDistance - prevIndexDistance))); return(result); }
void Start() { Debug.Log("Please read the comments at the top before using the runtime API!"); // Create Road Network object roadNetwork = new ERRoadNetwork(); // Create road // ERRoad road = roadNetwork.CreateRoad(string name); // ERRoad road = roadNetwork.CreateRoad(string name, Vector3[] markers); // ERRoad road = roadNetwork.CreateRoad(string name, ERRoadType roadType); // ERRoad road = roadNetwork.CreateRoad(string name, ERRoadType roadType, Vector3[] markers); ERRoadType roadType = new ERRoadType(); roadType.roadWidth = 6; roadType.roadMaterial = Resources.Load("Materials/roads/single lane") as Material; Vector3[] markers = new Vector3[4]; markers[0] = new Vector3(200, 5, 200); markers[1] = new Vector3(250, 5, 200); markers[2] = new Vector3(250, 5, 250); markers[3] = new Vector3(300, 5, 250); road = roadNetwork.CreateRoad("road 1", roadType, markers); // Add Marker: ERRoad.AddMarker(Vector3); road.AddMarker(new Vector3(300, 5, 300)); // Add Marker: ERRoad.InsertMarker(Vector3); road.InsertMarker(new Vector3(275, 5, 235)); // Delete Marker: ERRoad.DeleteMarker(int index); road.DeleteMarker(2); // Set the road width : ERRoad.SetWidth(float); // road.SetWidth(10); // Set the road material : ERRoad.SetMaterial(Material); // Material mat = Resources.Load("Materials/roads/single lane") as Material; // road.SetMaterial(mat); // Build Road Network roadNetwork.BuildRoadNetwork(); // Restore Road Network // roadNetwork.RestoreRoadNetwork(); // create dummy object go = GameObject.CreatePrimitive(PrimitiveType.Cube); }
// Adds a road, checking connections/intersections // Attempts to reduce chopiness in road merging // Uses road merging technique mentioned in Chris Hay's independent work // If angle < 30 degrees, connect roads as one // ****This isn't actually doing anything right now void addRoad(ERRoad toAdd) { /* for (int i = 0; i < currentThreadRoads.Count; i++) { * ERRoad existing = currentThreadRoads [i]; * Vector3 sharedPos = shareNode (existing, toAdd); * ERConnection[] conns = roadNetwork.LoadConnections (); * if (sharedPos.y >= 0) { * //ERConnection conn = roadNetwork.InstantiateConnection(conns[10], "conn", sharedPos, new Vector3(0.0f, 0.0f)); * //toAdd.ConnectToEnd (conn,0); * } * }*/ currentThreadRoads.Add(toAdd); }
// Checks if two roads share a node Vector3 shareNode(ERRoad road1, ERRoad road2) { Vector3[] markers1 = road1.GetMarkerPositions(); Vector3[] markers2 = road2.GetMarkerPositions(); // bool share = false; foreach (Vector3 v1 in markers1) { foreach (Vector3 v2 in markers2) { if (vectorsCloseEqual(v1, v2)) { return(v2); } } } return(new Vector3(0, -100, 0)); }
public RoadLine[] GenerateRoadNodes(ERRoad road, Road roadLines, float nodeDefinition, int definition, int count, int linesCount, bool invertFirst, bool oneWay) { RoadLine[] lines = new RoadLine[linesCount];//(count*(linesCount/2)); float plusMinus = 1f; int elCount = (int)(road.roadScript.distances[road.roadScript.distances.Count - 1] / nodeDefinition); if (elCount == 0) { elCount = 2; } if ((float)elCount % 2 != 0f) { elCount += 1; } for (int i = 0; i < linesCount; i++) { GameObject tempGo = new GameObject("Line" + (i), typeof(RoadLine)); tempGo.transform.SetParent(roadLines.transform); lines[i] = (tempGo.GetComponent <RoadLine>()); lines[i].GraphNodes = new List <GraphNode>(elCount / linesCount); lines[i].road = roadLines; plusMinus *= -1f; lines[i].GraphNodes.AddRange(GenerateOneLine(road, roadLines, (linesCount > 1 ? (road.roadScript.roadWidth / 2f) : 0f) * plusMinus, definition, elCount, oneWay ? !invertFirst : (plusMinus < 0f))); if (plusMinus > 0f) { plusMinus += (road.roadScript.roadWidth / 4f); } } for (int i = 0; i < linesCount; i++) { for (int j = 0; j < lines[i].GraphNodes.Count; j++) { lines[i].GraphNodes[j].Transform.SetParent(lines[i].transform); } } return(lines); }
/// <summary> /// Place a gameobject on the road at marker 0 looking at marker 1 /// </summary> private void AutoPlaceGameObject() { if (!editor.extension.roadSettings.autoPlaceGameObject) { return; } if (editor.extension.roadSettings.placementGameObject == null) { Debug.LogError("No GameObject specified"); return; } ERRoadNetwork erRoadNetwork = new ERRoadNetwork(); ERRoad erRoad = erRoadNetwork.GetRoadByGameObject(editor.extension.roadSettings.road); if (erRoad == null) { Debug.LogError("No road gameobject specified"); return; } if (erRoad.GetMarkerCount() < 2) { Debug.LogError("At least 2 markers required"); return; } GameObject gameObject = editor.extension.roadSettings.placementGameObject; // get marker with index 0 and 1 Vector3 positionA = erRoad.GetMarkerPosition(0); Vector3 positionB = erRoad.GetMarkerPosition(1); Bounds prefabBounds = BoundsUtils.GetPrefabBounds(gameObject); // position at marker position gameObject.transform.position = positionA; // look at 2nd marker gameObject.transform.LookAt(positionB); }
public void OnEnable() { biomeMaskArea = editor.FindProperty(x => x.roadSettings.biomeMaskArea); road = editor.FindProperty(x => x.roadSettings.road); smoothEnabled = editor.FindProperty(x => x.roadSettings.smoothEnabled); closedTrack = editor.FindProperty(x => x.roadSettings.closedTrack); minDistance = editor.FindProperty(x => x.roadSettings.minDistance); autoPlaceGameObject = editor.FindProperty(x => x.roadSettings.autoPlaceGameObject); placementGameObject = editor.FindProperty(x => x.roadSettings.placementGameObject); #if EASY_ROADS // create a reference to the road network in the scene erRoadNetwork = new ERRoadNetwork(); erRoad = null; if (road.objectReferenceValue != null) { erRoad = erRoadNetwork.GetRoadByGameObject(road.objectReferenceValue as GameObject); } #endif }
public void ClearRoad() { erRoad = erRoadNetwork.GetRoadByGameObject(road.objectReferenceValue as GameObject); if (erRoad == null) { Debug.LogError("No road gameobject specified"); return; } // the mask didn't get refreshed with the road, it stayed the old one => according to raoul this helps: Object.DestroyImmediate(erRoad.gameObject.GetComponent <AwesomeTechnologies.VegetationMaskLine>()); // delete all markers // TODO: find out how to do that properly while (erRoad.GetMarkerCount() > 0) { erRoad.DeleteMarker(0); } erRoad.Refresh(); }
/// <summary> /// Methode zum Platzieren des Autos am Anfang. /// </summary> private void PlaceCameraCar() { // Das Auto auf die rechte erste Spur platzieren ERRoad firstRoad = network.GetRoads().First(); Vector3 firstSplineRightSide = firstRoad.GetSplinePointsRightSide()[0]; Vector3 firstMarker = firstRoad.GetMarkerPosition(0); Vector3 rightMiddleLane = Vector3.zero; // Das Position je nach Anzahl der Spuren interpolieren switch (this.numberOfTracks) { case 8: rightMiddleLane = Vector3.Slerp(firstMarker, firstSplineRightSide, 0.85f); break; case 6: rightMiddleLane = Vector3.Slerp(firstMarker, firstSplineRightSide, 0.825f); break; case 4: rightMiddleLane = Vector3.Slerp(firstMarker, firstSplineRightSide, 0.75f); break; case 2: default: rightMiddleLane = Vector3.Slerp(firstMarker, firstSplineRightSide, 0.5f); break; } // Das Auto an die richtige Positions etzen cameraCar.gameObject.transform.position = rightMiddleLane; cameraCar.gameObject.transform.rotation = Quaternion.identity; // Ist platziert setzen isPlaced = true; }
public List <GraphNode> GenerateOneLine(ERRoad road, Road roadLines, float horizontalSep, int definition, int count, bool inverted) { List <GraphNode> nodes = new List <GraphNode>(count * 2); Vector3 vect1 = Vector3.zero, POS = default(Vector3), pos, tempVect = Vector3.zero, prevTempVect = Vector3.zero; GameObject temp; float percent = 0f; GraphNode node; road.roadScript.distances.Clear(); road.SetDistances(); float max = road.roadScript.distances[road.roadScript.distances.Count - 1], min = road.roadScript.distances[0]; int counter = 0; int currentElement = 0; for (int i = 0; i < count; i += 1) { percent = (float)i / (float)count; if (inverted) { percent = 1f - ((float)i / (float)count); } percent = Mathf.Lerp(min, max, percent); if (i == 0) { if (!inverted) { percent = min; } else { percent = max; } } if (i == count - 1) { if (!inverted) { percent = max; } else { percent = min; } } //Debug.Log(road.roadScript.transform.name + " " + currentElement + " " + percent + " "+ road.roadScript.distances.Count); vect1 = GetPosition(road, percent); tempVect = (Quaternion.AngleAxis(90, Vector3.up) * (GetPosition(road, percent + 0.01f) - vect1).normalized) * (horizontalSep * 0.4f); if (inverted && i == 0) { tempVect = (Quaternion.AngleAxis(90, Vector3.up) * (GetPosition(road, percent - 1f) - vect1).normalized * -1f) * (horizontalSep * 0.4f); } if ((!inverted && i != count - 1) || (inverted)) { prevTempVect = tempVect; } else { tempVect = prevTempVect; } vect1 += tempVect; pos = vect1;//(Vector3.Lerp(splinesAtLeft[currentElement], splinesAtRight[currentElement], horizontalSep/Vector3.Distance(splinesAtLeft[currentElement], splinesAtRight[currentElement]))); pos += Vector3.up * 2f; temp = new GameObject("NavNode " + counter, typeof(GraphNode)); nodes.Add(temp.GetComponent <GraphNode>()); node = nodes[nodes.Count - 1]; node.OverrideDefinition = true; node.OverrideDefinitionValue = definition; node.MaxSpeed = 35f; node.Transform.position = pos; temp.transform.SetParent(roadLines.transform); //GameObject tempGo = new GameObject(tempVect.ToString()); //tempGo.transform.position = pos; //tempGo.transform.SetParent(node.transform); counter++; } currentElement = 0; for (int i = 1; i < nodes.Count; i++) { nodes[i - 1].ConnectedNodes.Add(nodes[i]); percent = (float)(i) / (float)count - (1f / (float)count) / 2f; if (inverted) { percent = 1f - (((float)(i) / (float)count) - (1f / (float)count) / 2f); } percent = Mathf.Lerp(min, max, percent); if (i == 1) { if (!inverted) { percent = min; } else { percent = max; } } //if (i == count - 1) //{ // if (!inverted) // { // currentElement = road.GetSplinePointsCenter().Length - 1; // percent = max; // } // else // { // currentElement = 0; // percent = min; // } //} if (inverted && i == 1) { vect1 = Vector3.Lerp(nodes[i - 1].transform.position, nodes[i].transform.position, 0.5f); } else { vect1 = GetPosition(road, percent); vect1 += (Quaternion.AngleAxis(90, Vector3.up) * (GetPosition(road, percent + 0.01f) - vect1).normalized) * (horizontalSep * 0.4f); vect1 += Vector3.up * 2f; } nodes[i - 1].LinksBezierHelpers.Add(vect1); } return(nodes); }
private void SetNodes(Transform parent) { try { //Problem in that the loop is finding itself //This avoids recursing a folder that was created by this process if (parent.name.Contains(nodeFolderName)) { return; } //TODO: will need to check for the preexisting nodes, and delete them // "Traffic Nodes Right Lane(0)" bool isRight = true; string sSide = "Right"; string roadName = parent.parent.name; //Hack: use the name to determine if this is the Right or Left hand side if (parent.name.ToLower().Contains("left")) { isRight = false; sSide = "Left"; } //Get width of road, to get the number of lanes ERRoad erRoad = roadNetwork.GetRoadByName(roadName); ERRoadType roadType = erRoad.GetRoadType(); float roadWidth = roadType.roadWidth; byte laneCount = System.Convert.ToByte((roadType.roadWidth / 2) / laneWidth); List <Transform> trafficNodes = new List <Transform>(); Transform nodeChild; for (byte b = 0; b < laneCount; b++) { string folderName = nodeFolderName + " " + sSide + " Lane (" + b.ToString() + ")"; //todo NOT FINDING IT WHEN IT IS INDEED there Transform tempFolder = parent.parent.Find(folderName); //Check for the existance of this folder, if it already exists, delete it. //The road has been adjusted and it is safer to assume that the old nodes are no longer correct //...just in case if (tempFolder != null) { GameObject.DestroyImmediate(tempFolder.gameObject); } GameObject folder = new GameObject(folderName); if (b == 0) { //Remove existing Traffic Nodes from the folder that they were created //Moving them insures that they are not moved again, in a forever recursive loop //and to know they are completed, and not readjusted. if (isRight) { for (int i = 0; i < parent.childCount; i++) { //NOTE: Be aware that when creating the Side Object the "Combine Objects" checkbox MUST be unchecked // otherwise a few of these children will not be TrafficSystemNodes and that will cause all sorts of issues. nodeChild = parent.GetChild(i); nodeChild.name = roadName + " " + sSide + " node (" + i + ")"; trafficNodes.Add(nodeChild); } } else { int iLoop = 0; for (int i = (parent.childCount - 1); i > -1; i--) { nodeChild = parent.GetChild(i); nodeChild.name = roadName + " " + sSide + " node (" + iLoop + ")"; trafficNodes.Add(nodeChild); iLoop++; } } //Add to new parent foreach (Transform trafficNode in trafficNodes) { trafficNode.SetParent(folder.transform); } //Connect node to it's next neighbor ConnectNodes(folder); } else { // PROCESS // * Create new nodes // * Place them // * Connect them to each other - still a bit of an issue here //TODO // * Connect them to the previous Lane // * Connect previous lane to this lane //Create the nodes and place them for (int i = 0; i < trafficNodes.Count; i++) { float nodePosition = this.laneWidth; if (isRight) { nodePosition = -(this.laneWidth); } Transform trafficNode = Instantiate(trafficNodeInstance, trafficNodes[i].position + trafficNodes[i].right * nodePosition, trafficNodes[i].rotation); trafficNode.gameObject.isStatic = true; trafficNode.name = roadName + " " + sSide + " node (" + i + ")"; trafficNode.SetParent(folder.transform); //Connect to previous lane //trafficNodes[i] = trafficNode; //TODO: connect to next node, BUT this hasn't been created yet so.... //Do I need another LIST? Do I update the current list with the new Node, then in a separate loop connect them? //if (i < (folder.transform.childCount - 1)) //{ // TrafficSystemNode nextNode = folder.transform.GetChild(i + 1).GetComponent<TrafficSystemNode>(); // folder.transform.GetChild(i).GetComponent<TrafficSystemNode>().m_connectedChangeLaneNodes.Clear(); //To insure that previous values are removed // folder.transform.GetChild(i).GetComponent<TrafficSystemNode>().m_connectedChangeLaneNodes.Add(nextNode); //} } //folder.transform.SetParent(parent.parent); //Connect node to it's next neighbor ConnectNodes(folder); //Connect to Previous nodes to Current nodes folderName = nodeFolderName + " " + sSide + " Lane (" + (b - 1).ToString() + ")"; GameObject previousFolder = parent.parent.Find(folderName).gameObject; ConnectLanes(folder, previousFolder); } folder.transform.SetParent(parent.parent); } //DestroyImmediate(parent.gameObject); //Remove the original folder, causes an issue with the loop //TODO: intersections (someday) } catch (System.Exception ex) { HBCLogging.logException(ex); } }
/// <summary> /// Methode zum Zeichnen einer geraden Straße. /// </summary> /// <param name="length">Die Länge der Straße.</param> /// <param name="minCars">Die minimale Anzahl der Autos auf dem Straßenteil.</param> /// <param name="maxCars">Die maximale Anzahl der Autos auf dem Straßenteil.</param> /// <param name="heightDifference">Der Höhenunterschied.</param> /// <param name="seed">Der Seed.</param> /// <returns>Die Straße.</returns> public ERRoad CreateStraight(float length, int minCars, int maxCars, float?heightDifference, string seed) { // Die Strecke neu holen this.network = new ERRoadNetwork(); this.network.BuildRoadNetwork(); // Den RoadType holen ERRoadType roadType = this.GetRandomRoadType(); // Hole die akutellen Streckenteile ERRoad[] currentRoads = network.GetRoads(); // Hole die Höhe der Strecke float fixHeightDifference = heightDifference ?? 0; // Lege die Positionen der Strecke an Vector3 startPosition = new Vector3(0, 0, 0); Vector3 middlePosition = new Vector3(0, fixHeightDifference / 2, length / 2); Vector3 endPosition = new Vector3(0, fixHeightDifference, length); ERRoad lastRoad = null; ERRoad road = null; if (currentRoads.Length > 0) { // Hole die letzte Strecke lastRoad = currentRoads.Last(); // Hole den letzten Punkt der Strecke Vector3[] markers = lastRoad.GetMarkerPositions(); Vector3 lastMarker = markers.Last(); // Die richtige Rotation ausrechnen Vector3 heading = (lastMarker - markers[markers.Length - 2]); Vector3 direction = heading / heading.magnitude; direction.y = 0; // Das Verhältnis zwischen x und z-Achse ausrechnen float x = direction.x / (direction.magnitude); float z = direction.z / (direction.magnitude); Vector3[] streetVectors = new Vector3[(int)length]; float heightPart = fixHeightDifference / length; for (int lengthPart = 0; lengthPart < length; lengthPart++) { streetVectors[lengthPart] = lastMarker + new Vector3(x * lengthPart, heightPart * lengthPart, z * lengthPart); } // Generiere Straße road = network.CreateRoad("Straight" + currentRoads.Length, roadType, streetVectors); } else { // Generiere erste Straße road = network.CreateRoad("Straight" + currentRoads.Length, roadType, new Vector3[] { startPosition, middlePosition, endPosition }); } // Erstelle die Strecke mit einem eindeutigen Namen customEasyRoads.Add(new CustomEasyRoad(car, road, minCars, maxCars, numberOfTracks)); return(road); }
/// <summary> /// Erstellt eine Kurve anhand eines Winkels, der Länge der Kurve und den Positionen des aktuellen und vorherigen Straßen Elementes. /// </summary> /// <param name="angle">Der Winkel.</param> /// <param name="length">Die Länge des Straßenelementes.</param> /// <param name="heightDifference">Die Höhendifferenz für den Streckenabschnitt.</param> /// <param name="minCars">Die minimale Anzahl an Autos auf diesem Streckenabschnitt.</param> /// <param name="maxCars">Die maximale Anzahl an Autos auf diesem Streckenabschnitt.</param> /// <param name="seed">Der Seed des Random-Generators.</param> /// <returns>Die Kurve.</returns> public ERRoad CreateCurve(float angle, float length, float?heightDifference, int minCars, int maxCars, string seed) { // Die Strecke neu holen this.network = new ERRoadNetwork(); this.network.BuildRoadNetwork(); // hole die Höhendifference float fixHeightDifference = heightDifference ?? 0f; // Die StartPosition initialisieren. Vector3 startPosition = new Vector3(0, 0, 0); // Die Ausrichtung initialisieren (default ist z-Richtung). Vector3 heading = new Vector3(0, 0, 1); // Den RoadType holen ERRoadType roadType = this.GetRandomRoadType(); // Hole die Position des letzten Streckenabschnitts, wenn vorhanden. ERRoad lastRoad = null; if (network.GetRoads().Length > 0) { lastRoad = network.GetRoads().Last(); Vector3[] markers = lastRoad.GetMarkerPositions(); Vector3 lastPosition = markers.Last(); // Die Startposition an den letzten Streckenabschnitt anpassen. startPosition = lastPosition; // Die Ausrichtung in Bezug auf den vorherigen Streckenabschnitt holen. Vector3 secondToLast = markers[markers.Count() - 2]; heading = lastPosition - secondToLast; heading.y = 0; } // Den (geraden) Richtungsvektor berechnen. Vector3 direction = heading / heading.magnitude; // Der Vektor der y-Achse Vector3 yAxis = new Vector3(0, 1, 0); // Die Anzahl an zu berechnenden Positionen für die Kurve int numbPositions = Convert.ToInt32(Math.Abs(angle)); float positionPercentage = numbPositions * percentageEven; // Das Array mit den neuen Positionen. Vector3[] curvePositions = new Vector3[numbPositions]; curvePositions[0] = startPosition; // es werden in 1-Grad-Schritten Positionen berechnet. float anglePart = angle / Math.Abs(angle); float lengthPart = length / numbPositions; float heightPart = fixHeightDifference / (numbPositions - (2 * positionPercentage)); // Die Positionen berechnen. for (int i = 1; i < numbPositions; i++) { // Die direction für den nächsten Schritt berechnen if (i > 1) { heading = curvePositions[i - 1] - curvePositions[i - 2]; heading.y = 0; direction = heading / heading.magnitude; } // Die letzte Position holen. Vector3 oldPosition = curvePositions[i - 1]; // innerhalb des Prozent-Bereiches die Höhe anwenden. if (i > positionPercentage && i < (numbPositions - positionPercentage)) { oldPosition.y += heightPart.Truncate(5); } // Die neue Position berechnen. curvePositions[i] = oldPosition + Quaternion.AngleAxis(anglePart, yAxis) * direction * lengthPart; } // Die Kurve erzeugen. ERRoad thisRoad = this.network.CreateRoad("Curve" + network.GetRoads().Count(), roadType, curvePositions); customEasyRoads.Add(new CustomEasyRoad(car, thisRoad, minCars, maxCars, numberOfTracks)); return(thisRoad); }
void Start() { Debug_Log.Call_WriteLog("Please read the comments at the top of the runtime script (/Assets/EasyRoads3D/Scripts/runtimeScript) before using the runtime API!"); // Create Road Network object roadNetwork = new ERRoadNetwork(); // Create road // ERRoad road = roadNetwork.CreateRoad(string name); // ERRoad road = roadNetwork.CreateRoad(string name, Vector3[] markers); // ERRoad road = roadNetwork.CreateRoad(string name, ERRoadType roadType); // ERRoad road = roadNetwork.CreateRoad(string name, ERRoadType roadType, Vector3[] markers); // get exisiting road types // ERRoadType[] roadTypes = roadNetwork.GetRoadTypes(); // ERRoadType roadType = roadNetwork.GetRoadTypeByName(string name); // create a new road type ERRoadType roadType = new ERRoadType(); roadType.roadWidth = 6; roadType.roadMaterial = Resources.Load("Materials/roads/road material") as Material; // optional roadType.layer = 1; roadType.tag = "Untagged"; // roadType.hasMeshCollider = false; // default is true // roadType = roadNetwork.GetRoadTypeByName("Train Rail"); // Debug_Log.Call_WriteLog(roadType.roadMaterial); // create a new road Vector3[] markers = new Vector3[4]; markers[0] = new Vector3(200, 5, 200); markers[1] = new Vector3(250, 5, 200); markers[2] = new Vector3(250, 5, 250); markers[3] = new Vector3(300, 5, 250); road = roadNetwork.CreateRoad("road 1", roadType, markers); // road.SetResolution(float value):void; // Add Marker: ERRoad.AddMarker(Vector3); road.AddMarker(new Vector3(300, 5, 300)); // Add Marker: ERRoad.InsertMarker(Vector3); road.InsertMarker(new Vector3(275, 5, 235)); // road.InsertMarkerAt(Vector3 pos, int index): void; // Delete Marker: ERRoad.DeleteMarker(int index); road.DeleteMarker(2); // Set the road width : ERRoad.SetWidth(float width); // road.SetWidth(10); // Set the road material : ERRoad.SetMaterial(Material path); // Material mat = Resources.Load("Materials/roads/single lane") as Material; // road.SetMaterial(mat); // add / remove a meshCollider component // road.SetMeshCollider(bool value):void; // set the position of a marker // road.SetMarkerPosition(int index, Vector3 position):void; // road.SetMarkerPositions(Vector3[] position):void; // road.SetMarkerPositions(Vector3[] position, int index):void; // get the position of a marker // road.GetMarkerPosition(int index):Vector3; // get the position of a marker // road.GetMarkerPositions():Vector3[]; // Set the layer // road.SetLayer(int value):void; // Set the tag // road.SetTag(string value):void; // set marker control type // road.SetMarkerControlType(int marker, ERMarkerControlType type) : bool; // Spline, StraightXZ, StraightXZY, Circular // find a road // public static function ERRoadNetwork.GetRoadByName(string name) : ERRoad; // get all roads // public static function ERRoadNetwork.GetRoads() : ERRoad[]; // snap vertices to the terrain (no terrain deformation) // road.SnapToTerrain(true); // Build Road Network roadNetwork.BuildRoadNetwork(); // remove script components // roadNetwork.Finalize(); // Restore Road Network // roadNetwork.RestoreRoadNetwork(); // Show / Hide the white surfaces surrounding roads // public function roadNetwork.HideWhiteSurfaces(bool value) : void; // road.GetConnectionAtStart(): GameObject; // road.GetConnectionAtStart(out int connection): GameObject; // connections: 0 = bottom, 1= tip, 2 = left, 3 = right (the same for T crossings) // road.GetConnectionAtEnd(): GameObject; // road.GetConnectionAtEnd(out int connection): GameObject; // connections: 0 = bottom, 1= tip, 2 = left, 3 = right (the same for T crossings) // Snap the road vertices to the terrain following the terrain shape (no terrain deformation) // road.SnapToTerrain(bool value): void; // road.SnapToTerrain(bool value, float yOffset): void; // get the road length // road.GetLength() : float; // create dummy object go = GameObject.CreatePrimitive(PrimitiveType.Cube); }
public void Init(ERModularRoad modularRoad) { road = new ERRoadNetwork().GetRoadByGameObject(modularRoad.gameObject); totalDistance = road.GetDistance(); buildRoadVertexPath(); }
private void PlaceBuildings(Vector3[] markersSide, Vector3[] markersCenter, bool rightSide, ERRoad road) { try { //Process: //Get a building from the list, //Measure the building's width //Get the current sidePoint's position and count points until the difference is greater than/equal to the width of the building. If the end of the side markers is reached, don't place building //Get the angle based on the two points //Place the building at the center point of those two points //Move the building back away from edge of sidewalk (Min/Max values in the editors) //Optional: Move buildings back from road //Optional: Allow space between buildings float offset = 0; int currentMarker = 0; bool isProcessing = true; bool isFound = false; //Check if the building fits on this street-block float buildingDistance; const float increment = 0.2f; //The value incremented back from the road. do { //If there are no buildings left, no need to prcess anything, obviously. if (buildings.Count == 0) { isProcessing = false; break; } isFound = false; //reset Vector3 startMarker = markersSide[currentMarker]; GameObject building = buildings[buildings.Count - 1]; //Get the last one, and build in reverse. (allows removal from List without any issues) int buildingDepth = (building.GetComponent <BuildingModifier>().buildingDepth *buildingSizeMultiplier); int buildingWidth = (building.GetComponent <BuildingModifier>().buildingWidth *buildingSizeMultiplier); //loop to find the end position for (int i = (currentMarker + 1); i < markersSide.Length; i++) { Vector3 endMarker = markersSide[i]; buildingDistance = Vector3.Distance(startMarker, endMarker); if (buildingDistance >= buildingDepth) { Vector3[] vectors = new Vector3[] { startMarker, endMarker }; Vector3 centerPoint = CenterOfVectors(vectors); bool isRoad = false; offset = 0; //Reset do { isRoad = isInRoad(road.GetName(), centerPoint); //If this is on the road, then we need to move back a little bit until it's not touching the road if (isRoad) { offset += increment; var x = (currentMarker + i) / 2; centerPoint = markersCenter[x] + (markersCenter[x] - centerPoint) * offset; } } while (isRoad); //Optional: Push the building back farther from the road if (minBuildingBack > 0 || maxBuildingBack > 0) { var percent = Random.Range(1, 100); //This option allow a minimal amount of buildings to be moved back if (percent <= percentBuildingBack) { var offsetAddition = Random.Range(minBuildingBack, maxBuildingBack); if (offset == 0) { offsetAddition += (road.GetWidth() * .1f); } offset += offsetAddition; } } //if there is an offset value, push the building back farther if (offset > 0) { startMarker = markersCenter[currentMarker] + (markersCenter[currentMarker] - markersSide[currentMarker]) * -(offset / 2); endMarker = markersCenter[i] + (markersCenter[i] - markersSide[i]) * -(offset / 2); } //Need to move back the start and end markers if (rightSide) { building.transform.position = startMarker; building.transform.rotation = Quaternion.LookRotation(endMarker - startMarker, Vector3.up); } else { building.transform.position = endMarker; building.transform.rotation = Quaternion.LookRotation(startMarker - endMarker, Vector3.up); } isFound = true; currentMarker = i; break; } } if (isFound) { buildings.Remove(building); //Only remove this from the list if the building was placed } else { isProcessing = false; } //Optional: Allow space between buildings if (this.minBetweenBuildings > 0 && this.maxBetweenBuildings > 0) { isFound = false; //Reset float distanceBetweenBuildings = Random.Range(minBetweenBuildings, maxBetweenBuildings); Vector3 startPoint = markersSide[currentMarker]; for (int i = (currentMarker + 1); i < markersSide.Length; i++) { Vector3 endPoint = markersSide[i]; var buildingSeparation = Vector3.Distance(startPoint, endPoint); if (buildingSeparation >= distanceBetweenBuildings) { currentMarker = i; isFound = true; break; } } //In case we ran out of room for this side of the road, stop processing isProcessing = isFound; } } while (isProcessing); } catch (System.Exception ex) { Debug.LogError("Place Buildings Ex: " + ex.Message); } }