public void Spawn(int id, int subId) { float distance = Random.value * 0.8f + 0.1f; TrafEntry entry = system.GetEntry(id, subId); if (entry == null) { return; } InterpolatedPosition pos = entry.GetInterpolatedPosition(distance); if (!Physics.CheckSphere(pos.position, checkRadius, 1 << LayerMask.NameToLayer("Traffic"))) { GameObject go = GameObject.Instantiate(prefabs[Random.Range(0, prefabs.Length)], pos.position, Quaternion.identity) as GameObject; TrafAIMotor motor = go.GetComponent <TrafAIMotor>(); go.layer = 16; motor.currentIndex = pos.targetIndex; motor.currentEntry = entry; go.transform.LookAt(entry.waypoints[pos.targetIndex]); motor.system = system; motor.Init(); } }
void OnTriggerEnter(Collider other) { if (!other.CompareTag("Player")) { return; } redLight = false; var traf = transform.root.GetComponent <TrafSystem>(); var identifier = int.Parse(transform.parent.name); var entries = traf.intersections.Where(t => t.identifier == identifier + 1000); float minDist = 100000f; TrafEntry minEntry = null; foreach (var e in entries) { float d = Vector3.Distance(e.waypoints[0], other.transform.position); if (d < minDist) { minDist = d; minEntry = e; } } if (minEntry.light != null && minEntry.light.currentState == TrafLightState.RED) { redLight = true; entryPoint = minEntry.waypoints[0]; } }
public void SpawnFixed() { GameObject prefab = fixedPrefabs[Random.Range(0, fixedPrefabs.Length)]; var pMotor = prefab.GetComponent <TrafAIMotor>(); int index = Random.Range(0, pMotor.fixedPath.Count); int id = pMotor.fixedPath[index].id; int subId = pMotor.fixedPath[index].subId; float distance = Random.value * 0.8f + 0.1f; TrafEntry entry = system.GetEntry(id, subId); if (entry == null) { return; } InterpolatedPosition pos = entry.GetInterpolatedPosition(distance); if (!Physics.CheckSphere(pos.position, checkRadius * 3, 1 << LayerMask.NameToLayer("Traffic"))) { GameObject go = GameObject.Instantiate(prefab, pos.position, Quaternion.identity) as GameObject; TrafAIMotor motor = go.GetComponent <TrafAIMotor>(); motor.currentIndex = pos.targetIndex; motor.currentEntry = entry; go.transform.LookAt(entry.waypoints[pos.targetIndex]); motor.system = system; motor.Init(); motor.currentFixedNode = index; } }
public override void OnInspectorGUI() { DrawDefaultInspector(); EditorGUILayout.BeginVertical(); if (GUILayout.Button("GO!")) { var t = target as TrafIntersection; int sub = 0; foreach (var p in t.paths) { t.trafSystem.DeleteIntersectionIfExists(t.systemId, sub); p.subId = sub; var i = new TrafEntry(); i.identifier = 1000 + t.systemId; i.subIdentifier = sub++; i.intersection = t; i.path = p; i.road = GetRoad(p); i.light = GetLight(p.light); t.trafSystem.intersections.Add(i); //p.start.renderer.enabled = false; //p.end.renderer.enabled = false; } } EditorGUILayout.EndVertical(); }
public static void GoAll(TrafSystem trafSystem) { var allIntersections = Object.FindObjectsOfType(typeof(TrafIntersection)) as TrafIntersection[]; lightTable = new Dictionary <GameObject, TrafficLightContainer>(); foreach (var t in allIntersections) { int sub = 0; foreach (var p in t.paths) { if (t.trafSystem == null) { t.trafSystem = trafSystem; } t.trafSystem.DeleteIntersectionIfExists(t.systemId, sub); p.subId = sub; var i = new TrafEntry(); i.identifier = 1000 + t.systemId; i.subIdentifier = sub++; i.intersection = t; i.path = p; i.road = GetRoad(p); i.waypoints = new List <Vector3>(); i.spline = new List <SplineNode>(); i.spline.Add(new SplineNode() { position = p.start.transform.position, tangent = p.start.transform.forward }); i.spline.Add(new SplineNode() { position = p.end.transform.position, tangent = p.end.transform.forward }); foreach (var v in i.road.waypoints) { i.waypoints.Add(v.position); } i.light = GetLight(p.light); t.trafSystem.intersections.Add(i); //p.start.renderer.enabled = false; //p.end.renderer.enabled = false; } } lightTable.Clear(); }
//ANTONELLO private float calcolaDistanza(TrafEntry entry, GameObject go) { //questa funzione calcola vicino a che waypoint della entry ci troviamo //e calcola la distanza dall'inizio della entry fino al waypoint vicino al quale ci troviamo int numeroWaypoint = 1; foreach (Vector3 waypoint in entry.waypoints) { float miaX = go.transform.position.x; float miaY = go.transform.position.y; float miaZ = go.transform.position.z; float waypointX = waypoint.x; float waypointY = waypoint.y; float waypointZ = waypoint.z; if (System.Math.Abs(waypointX - miaX) <= 2f || System.Math.Abs(waypointZ - miaZ) <= 2f) { break; } numeroWaypoint++; } if (numeroWaypoint != 1) { float totalDist = 0f; for (int i = 1; i < entry.waypoints.Count; i++) { totalDist += Vector3.Distance(entry.waypoints[i], entry.waypoints[i - 1]); } float workingDist = 0f; for (int i = 1; i < numeroWaypoint; i++) { float thisDist = Vector3.Distance(entry.waypoints[i], entry.waypoints[i - 1]); workingDist += thisDist; } return((workingDist) / totalDist); } return(0); }
void Update() { if (!inited) { return; } if (!currentEntry.isIntersection() && currentIndex > 0 && !hasNextEntry) { //last waypoint in this entry, grab the next path when we are in range if (Vector3.Distance(nose.transform.position, currentEntry.waypoints[currentEntry.waypoints.Count - 1]) <= giveWayRegisterDistance) { var node = system.roadGraph.GetNode(currentEntry.identifier, currentEntry.subIdentifier); RoadGraphEdge newNode; if (fixedRoute) { if (++currentFixedNode >= fixedPath.Count) { currentFixedNode = 0; } newNode = system.FindJoiningIntersection(node, fixedPath[currentFixedNode]); } else { newNode = node.SelectRandom(); } if (newNode == null) { Debug.Log("no edges on " + currentEntry.identifier + "_" + currentEntry.subIdentifier); Destroy(gameObject); inited = false; return; } nextEntry = system.GetEntry(newNode.id, newNode.subId); nextTarget = nextEntry.waypoints[0]; hasNextEntry = true; nextEntry.RegisterInterest(this); //see if we need to slow down for this intersection intersectionCornerSpeed = Mathf.Clamp(1 - Vector3.Angle(nextEntry.path.start.transform.forward, nextEntry.path.end.transform.forward) / 90f, 0.4f, 1f); } } //check if we have reached the target waypoint if (Vector3.Distance(nose.transform.position, target) <= waypointThreshold)// && !hasStopTarget && !hasGiveWayTarget) { if (++currentIndex >= currentEntry.waypoints.Count) { if (currentEntry.isIntersection()) { currentEntry.DeregisterInterest(); var node = system.roadGraph.GetNode(currentEntry.identifier, currentEntry.subIdentifier); var newNode = node.SelectRandom(); if (newNode == null) { Debug.Log("no edges on " + currentEntry.identifier + "_" + currentEntry.subIdentifier); Destroy(gameObject); inited = false; return; } currentEntry = system.GetEntry(newNode.id, newNode.subId); nextEntry = null; hasNextEntry = false; targetTangent = (currentEntry.waypoints[1] - currentEntry.waypoints[0]).normalized; } else { if (hasStopTarget || hasGiveWayTarget) { target = nextEntry.waypoints[0]; } else { currentEntry = nextEntry; nextEntry = null; hasNextEntry = false; targetTangent = Vector3.zero; } } if (!hasStopTarget && !hasGiveWayTarget) { currentIndex = 0; } } if (currentIndex > 1) { targetTangent = Vector3.zero; } if (!hasStopTarget && !hasGiveWayTarget) { target = currentEntry.waypoints[currentIndex]; } } SteerCar(); if (hasNextEntry && nextEntry.isIntersection() && nextEntry.intersection.stopSign) { if (stopEnd == 0f) { hasStopTarget = true; stopTarget = nextTarget; stopEnd = Time.time + stopLength; } else if (Time.time > stopEnd) { if (nextEntry.intersection.stopQueue.Peek() == this) { hasGiveWayTarget = false; hasStopTarget = false; stopEnd = 0f; } } } if (hasNextEntry && nextEntry.isIntersection() && !nextEntry.intersection.stopSign) { //check next entry for stop needed if (nextEntry.MustGiveWay()) { hasGiveWayTarget = true; stopTarget = target; } else { hasGiveWayTarget = false; } } if (!hasGiveWayTarget && hasNextEntry && nextEntry.light != null) { if (!hasStopTarget && nextEntry.light.State == TrafLightState.RED) { //light is red, stop here hasStopTarget = true; stopTarget = nextTarget; } else if (hasStopTarget && nextEntry.light.State == TrafLightState.GREEN) { //green light, go! hasStopTarget = false; return; } else if (!hasStopTarget && nextEntry.light.State == TrafLightState.YELLOW) { //yellow, stop if we aren't zooming on through //TODO: carry on if we are too fast/close if (Vector3.Distance(nextTarget, nose.transform.position) > yellowLightGoDistance) { hasStopTarget = true; stopTarget = nextTarget; } } } float targetSpeed = maxSpeed; //check in front of us if (Time.time > nextRaycast) { hitInfo = new RaycastHit(); somethingInFront = CheckFrontBlocked(out hitInfo); nextRaycast = NextRaycastTime(); } if (somethingInFront) { float frontSpeed = Mathf.Clamp((hitInfo.distance - 1f) / 3f, 0f, maxSpeed); if (frontSpeed < 0.2f) { frontSpeed = 0f; } targetSpeed = Mathf.Min(targetSpeed, frontSpeed); } if (hasStopTarget || hasGiveWayTarget) { Vector3 targetVec = (stopTarget - nose.transform.position); float stopSpeed = Mathf.Clamp(targetVec.magnitude * (Vector3.Dot(targetVec, nose.transform.forward) > 0 ? 1f : 0f) / 3f, 0f, maxSpeed); if (stopSpeed < 0.24f) { stopSpeed = 0f; } targetSpeed = Mathf.Min(targetSpeed, stopSpeed); } //slow down if we need to turn if (currentEntry.isIntersection() || hasNextEntry) { targetSpeed = targetSpeed * intersectionCornerSpeed; } else { targetSpeed = targetSpeed * Mathf.Clamp(1 - (currentTurn / maxTurn), 0.1f, 1f); } if (targetSpeed > currentSpeed) { currentSpeed += Mathf.Min(maxAccell * Time.deltaTime, targetSpeed - currentSpeed); } else { currentSpeed -= Mathf.Min(maxBrake * Time.deltaTime, currentSpeed - targetSpeed); if (currentSpeed < 0) { currentSpeed = 0; } } }
//ANTONELLO private void guidaAutomaticaSF() { //Vector3 tempPos = transform.position; int id = Random.Range(0, maxIdent); int subId = Random.Range(0, maxSub); //float distance = Random.value * 0.8f + 0.1f; GameObject go = ottieniRiferimentoPlayer(); TrackController trackController = TrackController.Instance; TrafEntry entry = trackController.GetCurrentTrafEntry(); //-> ottengo la entry corrente //TrafEntry entryOk = null; //lo scopo della funziona calcolaDistanza è settare la variabile distance che farà si che verrà settato correttamente il waypoint target float distance = calcolaDistanza(entry, go); //entry = system.GetEntry(id, subId); //-> serve a ottenere la entry di un determinato punto, bisogna indicare il giusto id e subid if (entry == null) { Debug.Log("Entry = null"); return; } InterpolatedPosition pos = entry.GetInterpolatedPosition(distance); if (!Physics.CheckSphere(pos.position, checkRadius, 1 << LayerMask.NameToLayer("Traffic"))) { GameObject nose = new GameObject("nose"); nose.transform.SetParent(go.transform); nose.transform.localPosition = new Vector3(0, 0.5f, 2f); nose.transform.localRotation = Quaternion.identity; nose.transform.localScale = new Vector3(2f, 2f, 2f); TrafAIMotor motor = go.AddComponent <TrafAIMotor>(); GameObject colliderOstacoli = new GameObject("colliderOstacoli"); colliderOstacoli.transform.SetParent(go.transform); BoxCollider boxColliderOstacoli = colliderOstacoli.AddComponent <BoxCollider>(); boxColliderOstacoli.isTrigger = true; colliderOstacoli.transform.localPosition = new Vector3(0f, 0.65f, 7f); colliderOstacoli.transform.localScale = new Vector3(1f, 1f, 1f); colliderOstacoli.transform.localRotation = Quaternion.identity; boxColliderOstacoli.size = new Vector3(3f, 0.75f, 10f); TrafAIMotor.GestoreCollisioni gestore = colliderOstacoli.AddComponent <TrafAIMotor.GestoreCollisioni>(); gestore.setMotor(motor); //L'ISTRUZIONE SOTTO FA TELETRASPORTARE L'AUTO NELLA POSIZIONE pos.position //go.transform.position = pos.position; //go.AddComponent<TrafWheels>(); motor.currentIndex = pos.targetIndex; motor.currentEntry = entry; //L'istruzione sotto ruota la macchina in direzione del waypoint target //go.transform.LookAt(entry.waypoints[pos.targetIndex]); motor.system = system; motor.nose = nose; motor.raycastOrigin = nose.transform; motor.targetHeight = 0f; motor.waypointThreshold = 3f; guidaAutomatica = true; /*motor.fixedRoute = true; * * //RoadGraphEdge edge = new RoadGraphEdge(); * //edge.id = 5; edge.subId = 0; * RoadGraphEdge edge1 = new RoadGraphEdge(); * edge1.id = 1003; edge1.subId = 4; * RoadGraphEdge edge2 = new RoadGraphEdge(); * edge2.id = 3; edge2.subId = 1; * //RoadGraphEdge edge3 = new RoadGraphEdge(); * //edge3.id = 4; edge3.subId = 3; * * List<RoadGraphEdge> listaEdge = new List<RoadGraphEdge>(); * //listaEdge.Add(edge); * listaEdge.Add(edge1); * listaEdge.Add(edge2); * //listaEdge.Add(edge3); * motor.fixedPath = listaEdge;*/ motor.Init(); } else { guidaAutomaticaSF(); //è una ricorsione, fa si che si ripete la funzione finchè tutto vada bene } }
public GameObject Spawn(TrafEntry entry, bool unseenArea = false, CarAIController sameCar = null) { if (entry == null) { return(null); } float distance = Random.value * 0.8f + 0.1f; InterpolatedPosition pos = entry.GetInterpolatedPosition(distance); if (!Physics.CheckSphere(pos.position, checkRadius, NPCSpawnCheckBitmask)) { GameObject go; if (sameCar != null) //If it is the same car simply reposition it { go = sameCar.gameObject; go.transform.position = pos.position + Vector3.up; } else { go = GameObject.Instantiate(prefabs[Random.Range(0, prefabs.Length)], pos.position + Vector3.up * 3.5f, Quaternion.identity) as GameObject; } go.transform.LookAt(entry.waypoints[pos.targetIndex]); go.transform.SetParent(this.transform); // Put all spawned cars under this object for better organization var carAI = go.GetComponent <CarAIController>(); if (unseenArea) { if (!CheckSilentRespawnEligibility(carAI, Camera.main)) { if (sameCar == null) { DestroyImmediate(go); } return(null); } } else if (sameCar == null) //If it is a new spawn { //assign userid if (trafInfoManager.freeIdPool.Count == 0) { carAI.carID = trafInfoManager.GeneratePseudoRandomUID(); } else { carAI.carID = trafInfoManager.freeIdPool.Dequeue(); } carAI.RandomSelectCarPaintTexture(); ++totalTrafficCarCount; if (trafPerfManager != null) { trafPerfManager.AddAICar(carAI); } } // Init or Reinit AI motor TrafAIMotor motor = go.GetComponent <TrafAIMotor>(); motor.system = system; motor.Init(pos.targetIndex, entry); // Init or Reinit AI Controller carAI.Init(); return(go); } else { return(null); } }
public GameObject Spawn(int id, int subId, bool unseenArea = false, CarAIController sameCar = null) { TrafEntry entry = system.GetEntry(id, subId); return(Spawn(entry, unseenArea, sameCar)); }
public bool intersection; //if true I have reached the intersection public ProssimoTarget2(Vector3 target, bool intersection, TrafEntry trafEntry) { this.target = target; this.intersection = intersection; this.trafEntry = trafEntry; }
void SetTurnSignal() { TrafAIMotor trafAIMotor = transform.parent.gameObject.GetComponent <TrafAIMotor>(); if (trafAIMotor != null) { if (trafAIMotor.hasNextEntry) //this used to exclude the first road which is the only exception which I cannot exclude by the angle { //I am waiting at the intersection float dstToTarget = Vector3.Distance(rayCastPos.position, trafAIMotor.nextEntry.waypoints[0]); if (dstToTarget <= 20f) { TrafEntry nextRoadWaypoints = trafAIMotor.system.GetEntry(trafAIMotor.fixedPath[trafAIMotor.currentFixedNode].id, trafAIMotor.fixedPath[trafAIMotor.currentFixedNode].subId); //points of the next piece of road Vector3 heading = (nextRoadWaypoints.waypoints[nextRoadWaypoints.waypoints.Count - 1] - rayCastPos.position).normalized; float angle = Vector3.SignedAngle(rayCastPos.forward, heading, Vector3.up); //angle between heading and direction of PlayerCar if (angle < -20f) { if (!hasPlayedON) { turnLeftAudioSource.PlayOneShot(ResourceHandler.instance.audioClips[7]); hasPlayedON = true; } turnLeftAnim.SetBool("Turn", true); lastTurnSignal = TurnSignal.LEFT; hasPlayedOFF = false; } else if (angle > 20f) { if (!hasPlayedON) { turnRightAudioSource.PlayOneShot(ResourceHandler.instance.audioClips[7]); hasPlayedON = true; } turnRightAnim.SetBool("Turn", true); lastTurnSignal = TurnSignal.RIGHT; hasPlayedOFF = false; } } } else if ((!trafAIMotor.hasNextEntry && !trafAIMotor.currentEntry.isIntersection()) && Mathf.Abs(vehicleController.steerInput) <= 0.02f) //With the steerInput condition I assure that the turn signal is set off when steer has more or less angle equal to zero { if (lastTurnSignal.Equals(TurnSignal.LEFT)) { turnLeftAnim.SetBool("Turn", false); hasPlayedON = false; if (!hasPlayedOFF) { turnLeftAudioSource.PlayOneShot(ResourceHandler.instance.audioClips[6]); hasPlayedOFF = true; } } else if (lastTurnSignal.Equals(TurnSignal.RIGHT)) { turnRightAnim.SetBool("Turn", false); hasPlayedON = false; if (!hasPlayedOFF) { turnRightAudioSource.PlayOneShot(ResourceHandler.instance.audioClips[6]); hasPlayedOFF = true; } } } } }
private void GenerateRoadGraph() { var system = target as TrafSystem; system.roadGraph = new TrafRoadGraph(); foreach (var entry in system.entries) { Vector3 start = entry.waypoints[0]; Vector3 end = entry.waypoints[entry.waypoints.Count - 1]; //set up spline path entry.spline = new List <SplineNode>(); entry.spline.Add(new SplineNode() { position = entry.waypoints[0], tangent = (entry.waypoints[1] - entry.waypoints[0]).normalized }); for (int i = 1; i < entry.waypoints.Count - 1; i++) { entry.spline.Add(new SplineNode() { position = entry.waypoints[i], tangent = Vector3.Lerp((entry.waypoints[i] - entry.waypoints[i - 1]).normalized, (entry.waypoints[i + 1] - entry.waypoints[i]).normalized, 0.5f).normalized }); } entry.spline.Add(new SplineNode() { position = entry.waypoints[entry.waypoints.Count - 1], tangent = (entry.waypoints[entry.waypoints.Count - 1] - entry.waypoints[entry.waypoints.Count - 2]).normalized }); float minDist = 99999f; TrafEntry minEntry = null; //intersections we can end up at foreach (var isection in system.intersections) { float dist = Vector3.Distance(isection.waypoints[0], end); if (dist < minDist) { minDist = dist; minEntry = isection; } } if (minDist < maxEdgesConnectedDistance) { foreach (var e in system.intersections.FindAll(i => i.waypoints[0] == minEntry.waypoints[0])) { AddEdge(system.roadGraph.roadGraph, entry.identifier, entry.subIdentifier, e.identifier, e.subIdentifier); //fix spline end tangent entry.spline[entry.spline.Count - 1].tangent = e.path.start.transform.forward; } } //intersections we could have come from minDist = 99999f; minEntry = null; foreach (var isection in system.intersections) { float dist = Vector3.Distance(isection.waypoints[isection.waypoints.Count - 1], start); if (dist < minDist) { minDist = dist; minEntry = isection; } } if (minDist < maxEdgesConnectedDistance) { //dirty hack to exclude isection with no entry for 66_2 and 66_3 if (entry.identifier == 62 && (entry.subIdentifier == 2 || entry.subIdentifier == 3)) { //just ignore for now } else { foreach (var e in system.intersections.FindAll(i => i.waypoints[i.waypoints.Count - 1] == minEntry.waypoints[i.waypoints.Count - 1])) { AddEdge(system.roadGraph.roadGraph, e.identifier, e.subIdentifier, entry.identifier, entry.subIdentifier); //fix spline start tangent entry.spline[0].tangent = e.path.end.transform.forward; } } } } }
private void AutoFixRoadGraph() { var trafSystem = target as TrafSystem; foreach (var e in trafSystem.entries) { var node = trafSystem.roadGraph.GetNode(e.identifier, e.subIdentifier); if (node.edges == null) { Debug.Log(e.identifier + "_" + e.subIdentifier + "(non-intersection) has NULL edges, fixing..."); node.edges = new List <RoadGraphEdge>(); } if (node.edges.Count < 1) { Debug.Log(e.identifier + "_" + e.subIdentifier + "(non-intersection) has EMPTY edges, fixing"); //Start fixing Vector3 start = e.waypoints[0]; Vector3 end = e.waypoints[e.waypoints.Count - 1]; float minDist = 99999f; TrafEntry minEntry = null; foreach (var isection in trafSystem.intersections) { float dist = Vector3.Distance(isection.waypoints[0], end); if (dist < minDist) { minDist = dist; minEntry = isection; } } if (minDist < maxEdgesConnectedDistance) { foreach (var iEntry in trafSystem.intersections.FindAll(x => (x.waypoints[0] - minEntry.waypoints[0]).magnitude < 0.001f)) { AddEdge(trafSystem.roadGraph.roadGraph, e.identifier, e.subIdentifier, iEntry.identifier, iEntry.subIdentifier); } } if (node.edges.Count < 1) { Debug.Log(e.identifier + "_" + e.subIdentifier + "(non-intersection) still has EMPTY edges after the fix"); } else { Debug.Log(e.identifier + "_" + e.subIdentifier + "(non-intersection) now has " + node.edges.Count + " edges after the fix"); Debug.Log("Added edges: "); foreach (var edge in node.edges) { Debug.Log("Id: " + edge.id + " | SubId: " + edge.subId); } } Debug.Log("Fix done"); } } foreach (var i in trafSystem.intersections) { var node = trafSystem.roadGraph.GetNode(i.identifier, i.subIdentifier); if (node.edges == null) { Debug.Log(i.identifier + "_" + i.subIdentifier + "(intersection) has NULL edges, fixing..."); node.edges = new List <RoadGraphEdge>(); } if (node.edges.Count < 1) { Debug.Log(i.identifier + "_" + i.subIdentifier + "(intersection) has EMPTY edges, fixing"); //Start fixing Vector3 start = i.waypoints[0]; Vector3 end = i.waypoints[i.waypoints.Count - 1]; float minDist = 99999f; TrafEntry minEntry = null; foreach (var entry in trafSystem.entries) { float dist = Vector3.Distance(entry.waypoints[0], end); if (dist < minDist) { minDist = dist; minEntry = entry; } } if (minDist < maxEdgesConnectedDistance) { //dirty hack to exclude isection with no entry for 66_2 and 66_3 if (i.identifier == 62 && (i.subIdentifier == 2 || i.subIdentifier == 3)) { //just ignore for now } else { foreach (var eEntry in trafSystem.entries.FindAll(x => (x.waypoints[0] - minEntry.waypoints[0]).magnitude < 0.001f)) { AddEdge(trafSystem.roadGraph.roadGraph, i.identifier, i.subIdentifier, eEntry.identifier, eEntry.subIdentifier); } } } if (node.edges.Count < 1) { Debug.Log(i.identifier + "_" + i.subIdentifier + "(intersection) still has EMPTY edges after the fix"); } else { Debug.Log(i.identifier + "_" + i.subIdentifier + "(intersection) now has " + node.edges.Count + " edges after the fix"); Debug.Log("Added edges: "); foreach (var edge in node.edges) { Debug.Log("Id: " + edge.id + " | SubId: " + edge.subId); } } Debug.Log("Fix done"); } } }
} //NavigationLine of PlayerCar and TrafficCar in PCH public void DrawLine(GameObject car) { List <Vector3> initialList = new List <Vector3>(); TrafAIMotor trafAIMotor = car.GetComponent <TrafAIMotor>(); if (trafAIMotor != null) { bool hasNextEntryOk; TrafEntry nextEntryOk; int index; if (car.CompareTag("Player")) { //tesla hasNextEntryOk = trafAIMotor.hasNextEntry50; nextEntryOk = trafAIMotor.nextEntry50; if (trafAIMotor.hasNextEntry) { index = trafAIMotor.currentFixedNode; } else { index = trafAIMotor.currentFixedNode + 1; } } else { hasNextEntryOk = trafAIMotor.hasNextEntry; nextEntryOk = trafAIMotor.nextEntry; index = trafAIMotor.currentFixedNode; } if (hasNextEntryOk) { //I am waiting at the intersection TrafEntry nextRoadWaypoints = trafAIMotor.system.GetEntry(trafAIMotor.fixedPath[index].id, trafAIMotor.fixedPath[index].subId); //points of the next piece of road if (nextRoadWaypoints.waypoints.Count == 2) { LinePoints.Add(car.transform.position); List <Vector3> smoothedPoints = ChaikinCurve(nextEntryOk.waypoints.ToArray(), 4); //intersection points initialList.AddRange(smoothedPoints); initialList.Add(nextRoadWaypoints.waypoints[nextRoadWaypoints.waypoints.Count - 1]); } else if (nextRoadWaypoints.waypoints.Count > 2) { List <Vector3> smoothedPoints = new List <Vector3>(); smoothedPoints.Add(car.transform.position); smoothedPoints.Add(nextEntryOk.waypoints[0]); //intersection points smoothedPoints.AddRange(nextRoadWaypoints.waypoints); initialList.AddRange(ChaikinCurve(smoothedPoints.ToArray(), 2)); } } else if (!hasNextEntryOk && trafAIMotor.currentEntry.isIntersection()) { //I am crossing the intersection TrafEntry nextRoadWaypoints = trafAIMotor.system.GetEntry(trafAIMotor.fixedPath[trafAIMotor.currentFixedNode].id, trafAIMotor.fixedPath[trafAIMotor.currentFixedNode].subId); //points of the next piece of road if (nextRoadWaypoints.waypoints.Count == 2) { LinePoints.Add(car.transform.position); List <Vector3> smoothedPoints = ChaikinCurve(trafAIMotor.currentEntry.waypoints.ToArray(), 4); int nearest = CalculatePointDistance(smoothedPoints, car); Vector3 heading = smoothedPoints[nearest] - car.transform.position; if (Vector3.Dot(heading, car.transform.forward) > 0) { for (int i = nearest; i < smoothedPoints.Count; i++) { initialList.Add(smoothedPoints[i]); } } else { for (int i = nearest + 1; i < smoothedPoints.Count; i++) { initialList.Add(smoothedPoints[i]); } } initialList.Add(nextRoadWaypoints.waypoints[nextRoadWaypoints.waypoints.Count - 1]); } else if (nextRoadWaypoints.waypoints.Count > 2) //if more than 2, smooth and add all of them { List <Vector3> smoothedPoints = new List <Vector3>(); smoothedPoints.Add(car.transform.position); smoothedPoints.Add(trafAIMotor.currentEntry.waypoints[0]); //intersection points smoothedPoints.AddRange(nextRoadWaypoints.waypoints); smoothedPoints = ChaikinCurve(smoothedPoints.ToArray(), 2); int nearest = CalculatePointDistance(smoothedPoints, car); Vector3 heading = smoothedPoints[nearest] - car.transform.position; if (Vector3.Dot(heading, car.transform.forward) > 0) { for (int i = nearest; i < smoothedPoints.Count; i++) { initialList.Add(smoothedPoints[i]); } } else { for (int i = nearest + 1; i < smoothedPoints.Count; i++) { initialList.Add(smoothedPoints[i]); } } //initialList.AddRange(smoothedPoints); } } else if (!hasNextEntryOk && !trafAIMotor.currentEntry.isIntersection()) {//I am on curves or on straight lines LinePoints.Add(car.transform.position); if (trafAIMotor.currentEntry.waypoints.Count == 2) { initialList.Add(trafAIMotor.currentEntry.waypoints[trafAIMotor.currentEntry.waypoints.Count - 1]); } else if (trafAIMotor.currentEntry.waypoints.Count > 2) { List <Vector3> pointsToSmooth = ChaikinCurve(trafAIMotor.currentEntry.waypoints.ToArray(), 2); int nearest = CalculatePointDistance(pointsToSmooth, car); Vector3 heading = pointsToSmooth[nearest] - car.transform.position; if (Vector3.Dot(heading, car.transform.forward) > 0) { for (int i = nearest; i < pointsToSmooth.Count; i++) { initialList.Add(pointsToSmooth[i]); } } else { for (int i = nearest + 1; i < pointsToSmooth.Count; i++) { initialList.Add(pointsToSmooth[i]); } } } } foreach (var p in initialList) { Vector3 currentSpot = p; RaycastHit hit; Physics.Raycast(currentSpot + Vector3.up * 5, -Vector3.up, out hit, 100f, (1 << LayerMask.NameToLayer("EnvironmentProp"))); //the layer is EnvironmentProp and not Roads since there is a hidden mesh before roads! Vector3 correctedPoint = new Vector3(currentSpot.x, hit.point.y + 0.05f, currentSpot.z); LinePoints.Add(correctedPoint); } lineRenderer.positionCount = LinePoints.Count; lineRenderer.SetPositions(LinePoints.ToArray()); LinePoints.Clear(); } } //NavigationLine of PlayerCar and TrafficCar in SF
//ANTONELLO private void modificaTarget(bool waypointSaltato) { if (++currentIndex >= currentEntry.waypoints.Count) { //Debug.Log("Numero waypoints: " + currentEntry.waypoints.Count + "; currentIndex: " + currentIndex); if (currentEntry.isIntersection()) { currentEntry.DeregisterInterest(); var node = system.roadGraph.GetNode(currentEntry.identifier, currentEntry.subIdentifier); var newNode = node.SelectRandom(); //CONTROLLA QUESTO PEZZO DI CODICE; POTREBBE DISTRUGGERE LA MACCHINA if (newNode == null) { //Debug.Log("no edges on " + currentEntry.identifier + "_" + currentEntry.subIdentifier); Destroy(gameObject); inited = false; return; } currentEntry = system.GetEntry(newNode.id, newNode.subId); nextEntry = null; hasNextEntry = false; inizioValutazioneSemaforo = false; if (this.tag.Equals("Player")) { this.Property = "" + newNode.id; } targetTangent = (currentEntry.waypoints[1] - currentEntry.waypoints[0]).normalized; } else { if ((hasStopTarget || hasGiveWayTarget) && !waypointSaltato) //ANTONELLO { targetPrecedente = target; target = nextEntry.waypoints[0]; } else { if (nextEntry != null && nextEntry.identifier != 0) //ANTONELLO { currentEntry = nextEntry; nextEntry = null; hasNextEntry = false; inizioValutazioneSemaforo = false; targetTangent = Vector3.zero; if (this.tag.Equals("Player")) { this.Property = "" + currentEntry.identifier; } } //ANTONELLO if (waypointSaltato && (hasStopTarget || hasGiveWayTarget)) { hasStopTarget = false; hasGiveWayTarget = false; } } } if ((!hasStopTarget && !hasGiveWayTarget) || waypointSaltato) { currentIndex = 0; } } if (currentIndex > 1) { targetTangent = Vector3.zero; } if ((!hasStopTarget && !hasGiveWayTarget) || waypointSaltato) { targetPrecedente = target; target = currentEntry.waypoints[currentIndex]; } }
void Guida() { if (!inited) { return; } if (inchiodata) { inchioda(); return; } if (evitare) { evita(); return; } if (this.tag.Equals("Player")) { velocitaAttuale = GetComponent <Rigidbody>().velocity.magnitude; } else { velocitaAttuale = currentSpeed; } accelerazione = (velocitaAttuale - velocitaPrecedente) / Time.deltaTime; velocitaPrecedente = velocitaAttuale; TrafAIMotor motor = GetComponent <TrafAIMotor>(); motor.currentSpeed = currentSpeed; motor.hasStopTarget = hasStopTarget; motor.frenata = frenata; motor.luceStop = luceStop; motor.hasNextEntry = hasNextEntry; motor.currentEntry = currentEntry; motor.nextEntry = nextEntry; if (!currentEntry.isIntersection() && currentIndex > 0 && !hasNextEntry) { if (Vector3.Distance(nose.transform.position, currentEntry.waypoints[currentEntry.waypoints.Count - 1]) <= 60f && this.tag.Equals("Player")) //piu è alto e piu inizia prima la valutazione dell'intersezione (es. semaforo) { if (semaforo != currentEntry.identifier) { Semaforo = "" + currentEntry.identifier; //Setto la proprietà quando inizio a valutare il semaforo } } //last waypoint in this entry, grab the next path when we are in range //ANTONELLO //if(Vector3.Distance(nose.transform.position, currentEntry.waypoints[currentEntry.waypoints.Count - 1]) <= giveWayRegisterDistance) if (Vector3.Distance(nose.transform.position, currentEntry.waypoints[currentEntry.waypoints.Count - 1]) <= 40f) //era a 20 { var node = system.roadGraph.GetNode(currentEntry.identifier, currentEntry.subIdentifier); RoadGraphEdge newNode; if (fixedRoute) { if (++currentFixedNode >= fixedPath.Count) { currentFixedNode = 0; } newNode = system.FindJoiningIntersection(node, fixedPath[currentFixedNode]); } else { newNode = node.SelectRandom(); } if (newNode == null) { Debug.Log("no edges on " + currentEntry.identifier + "_" + currentEntry.subIdentifier); //ANTONELLO if (!this.tag.Equals("Player")) { Destroy(gameObject); } else { Property = "9999"; inchioda(); return; } inited = false; return; } nextEntry = system.GetEntry(newNode.id, newNode.subId); nextTarget = nextEntry.waypoints[0]; hasNextEntry = true; nextEntry.RegisterInterest(gameObject.GetComponent <TrafAIMotor>()); //see if we need to slow down for this intersection intersectionCornerSpeed = Mathf.Clamp(1 - Vector3.Angle(nextEntry.path.start.transform.forward, nextEntry.path.end.transform.forward) / 90f, 0.4f, 1f); } } if (hasNextEntry && !inizioValutazioneSemaforo && Vector3.Distance(nose.transform.position, nextTarget) <= 30f) { inizioValutazioneSemaforo = true; } float distanzaWaypointFramePrecedente = distanzaWaypoint; distanzaWaypoint = Vector3.Distance(nose.transform.position, target); //check if we have reached the target waypoint if (distanzaWaypoint <= waypointThreshold)// && !hasStopTarget && !hasGiveWayTarget) { distanzaWaypoint = 0; modificaTarget(false); //Debug.Log("Target = " + target.x + " " + target.y + " " + target.z); numeroWaypointSaltati = 0; } else { if (distanzaWaypointFramePrecedente != 0 && (distanzaWaypoint - distanzaWaypointFramePrecedente) > 0) { contatore++; if (contatore >= 3) { //abbiamo saltato il waypoint if ((numeroWaypointSaltati++) >= 7) { Destroy(gameObject); } Debug.Log("waypoint saltato"); distanzaWaypoint = 0; contatore = 0; modificaTarget(true); //Debug.Log("Target = " + target.x + " " + target.y + " " + target.z); //hasStopTarget = false; //hasGiveWayTarget = false; } } else { contatore = 0; } } Debug.DrawLine(this.transform.position, target); //SteerCar(); if (hasNextEntry && inizioValutazioneSemaforo && nextEntry.isIntersection() && nextEntry.intersection.stopSign && !autoScorretta) { if (stopEnd == 0f) { hasStopTarget = true; velocitaInizialeFrenata = velocitaAttuale; stopTarget = nextTarget; calcolaDistanzaIniziale(); stopEnd = Time.time + stopLength; } else if (Time.time > stopEnd) { if (nextEntry.intersection.stopQueue.Peek() == this) { hasGiveWayTarget = false; hasStopTarget = false; stopEnd = 0f; float distanza = Vector3.Distance(this.transform.position, stopTarget); if (distanza < 10f) { //evita che quando ci fermiamo a uno stop (un pochino prima dello stopTarget), riparte e si riferma allo stopTarget effettivo //nextEntry.intersection.stopSign = false; currentEntry = nextEntry; nextEntry = null; hasNextEntry = false; inizioValutazioneSemaforo = false; } } } } if (hasNextEntry && !hasGiveWayTarget && inizioValutazioneSemaforo && nextEntry.isIntersection() && !nextEntry.intersection.stopSign) { //check next entry for stop needed if (nextEntry.MustGiveWay()) { hasGiveWayTarget = true; velocitaInizialeFrenata = velocitaAttuale; stopTarget = nextTarget; calcolaDistanzaIniziale(); } else { hasGiveWayTarget = false; } } else { if (hasGiveWayTarget && !nextEntry.MustGiveWay()) { hasGiveWayTarget = false; } } if (!hasGiveWayTarget && hasNextEntry && inizioValutazioneSemaforo && nextEntry.light != null) { if (!hasStopTarget && nextEntry.light.State == TrafLightState.RED) { //light is red, stop here //ANTONELLO if (!autoScorretta) { hasStopTarget = true; velocitaInizialeFrenata = velocitaAttuale; stopTarget = nextTarget; calcolaDistanzaIniziale(); } //else autoScorretta = true, non rispetta i semafori rossi e passacomunque } else if (hasStopTarget && nextEntry.light.State == TrafLightState.GREEN) { //green light, go! //ANTONELLO hasStopTarget = false; } else if (!hasStopTarget && nextEntry.light.State == TrafLightState.YELLOW) { //yellow, stop if we aren't zooming on through //TODO: carry on if we are too fast/close if (Vector3.Distance(nextTarget, nose.transform.position) > yellowLightGoDistance) { //ANTONELLO hasStopTarget = true; velocitaInizialeFrenata = velocitaAttuale; stopTarget = nextTarget; calcolaDistanzaIniziale(); } //altrimenti non riesco a fermarmi, continuo } } float targetSpeed = maxSpeed; //float targetSpeed = Mathf.MoveTowards(currentSpeed, maxSpeed, 100f * Time.deltaTime); //lancio il raggio per vedere cosa ho davanti if (Time.time > nextRaycast) { hitInfo = new RaycastHit(); somethingInFront = CheckFrontBlocked(out hitInfo); nextRaycast = NextRaycastTime(); } if (somethingInFront) { if (hitInfo.collider.gameObject.tag.Equals("Player")) { currentSpeed = 0; return; } } if (frenata) { //ANTONELLO //se ho come target quello di fermarmi, diminuisco la velocità proporzionalmente fino al punto in cui devo fermarmi Vector3 vettoreDifferenza = frenataTarget - transform.position; float distanzaCorrente = 0; if (Math.Abs(vettoreDifferenza.x) > Math.Abs(vettoreDifferenza.z)) { distanzaCorrente = Math.Abs(vettoreDifferenza.x); } else { distanzaCorrente = Math.Abs(vettoreDifferenza.z); } if (this.tag.Equals("Player")) { distanzaCorrente -= 5f; } else { distanzaCorrente -= 6f; } Debug.DrawLine(frenataTarget, transform.position); //if (velocitaInizialeFrenata >= 6f) //{ targetSpeed = velocitaInizialeFrenata * distanzaCorrente / distanzaInizialeInchiodata; /*} else * { * targetSpeed = 6f * distanzaCorrente / distanzaInizialeInchiodata; * }*/ if (targetSpeed <= _pidPars.sogliaFermata) { targetSpeed = 0; //Debug.Log("target < 2"); } //else //Debug.Log("distanza Iniziale Inchiodata = " + distanzaInizialeInchiodata + "; distanzaCorrente = " + distanzaCorrente + "; targetSpeed: " + targetSpeed); } if (!frenata && !autoDavantiFrenata && (hasStopTarget || hasGiveWayTarget)) { /*Vector3 targetVec = (stopTarget - nose.transform.position); * * float stopSpeed = Mathf.Clamp(targetVec.magnitude * (Vector3.Dot(targetVec, nose.transform.forward) > 0 ? 1f : 0f) / 3f, 0f, maxSpeed); * if(stopSpeed < 0.24f) * stopSpeed = 0f; * * targetSpeed = Mathf.Min(targetSpeed, stopSpeed); * //Debug.Log("hasStopTarget true; targetSpeed: " + targetSpeed);*/ //ANTONELLO //se ho come target quello di fermarmi, diminuisco la velocità proporzionalmente fino al punto in cui devo fermarmi Vector3 vettoreDifferenza = stopTarget - transform.position; float distanzaCorrente = 0; if (Math.Abs(vettoreDifferenza.x) > Math.Abs(vettoreDifferenza.z)) { distanzaCorrente = Math.Abs(vettoreDifferenza.x); } else { distanzaCorrente = Math.Abs(vettoreDifferenza.z); } distanzaCorrente -= 2f; Debug.DrawLine(stopTarget, transform.position); targetSpeed = velocitaInizialeFrenata * distanzaCorrente / distanzaIniziale; /*if (velocitaInizialeFrenata >= 6f) * { * targetSpeed = velocitaInizialeFrenata * distanzaCorrente / distanzaIniziale; * } * else * { * targetSpeed = 6f * distanzaCorrente / distanzaIniziale; * }*/ if (targetSpeed <= _pidPars.sogliaFermata) { targetSpeed = 0; //Debug.Log("target < 2"); } //else //Debug.Log("distanza Iniziale = " + distanzaIniziale + "; distanzaCorrente = " + distanzaCorrente + "; targetSpeed: " + targetSpeed); } //slow down if we need to turn //if(currentEntry.isIntersection() || hasNextEntry) //ANTONELLO //if ((currentEntry.isIntersection() || hasNextEntry) && !hasStopTarget && !frenata) if ((currentEntry.isIntersection() || inizioValutazioneSemaforo) && !hasStopTarget && !hasGiveWayTarget && !frenata) { float min = 4; if (targetSpeed <= 4) { min = targetSpeed; } targetSpeed = Mathf.Clamp(targetSpeed * intersectionCornerSpeed, min, maxSpeed); /*targetSpeed = Mathf.MoveTowards(targetSpeed, targetSpeed * intersectionCornerSpeed, Time.fixedDeltaTime * 5f); * if (this.tag.Equals("Player")) * { * Debug.Log("IntersectionCornerSpeed: " + intersectionCornerSpeed + "; targetSpeed: " + targetSpeed); * }*/ } else { //DA TESTARE - ANTONELLO if (currentTurn > 5f || currentTurn < -5f) { //targetSpeed = targetSpeed * Mathf.Clamp(1 - (currentTurn / maxTurn), 0.1f, 1f); targetSpeed = targetSpeed * Mathf.Clamp(1 - (Math.Abs(currentTurn) / maxTurn), 0.2f, 1f); } } float targetSpeedIniziale = targetSpeed; if (targetSpeed > currentSpeed) { float distanzaCorrente = 0; if (hasStopTarget || hasGiveWayTarget) { Vector3 vettoreDifferenza = stopTarget - transform.position; if (Math.Abs(vettoreDifferenza.x) > Math.Abs(vettoreDifferenza.z)) { distanzaCorrente = Math.Abs(vettoreDifferenza.x); } else { distanzaCorrente = Math.Abs(vettoreDifferenza.z); } } //Debug.Log("distanza corrente ripartenza: " + distanzaCorrente + "; targetSpee:" +targetSpeed); //if ((targetSpeed - currentSpeed) < 1 && (hasStopTarget || frenata) && distanzaCorrente < 3f) if ((hasStopTarget || hasGiveWayTarget) && distanzaCorrente < 6f) { //fa si che quando ci fermiamo allo stop o per via di una inchiodata la macchina rimanga ferma //currentSpeed = 0; } else { //currentSpeed += Mathf.Min(maxAccell * Time.deltaTime, targetSpeed - currentSpeed); currentSpeed = targetSpeed; } //currentSpeed = Mathf.MoveTowards(currentSpeed, targetSpeed, Time.fixedDeltaTime * _pidPars.velocitaFrenata); } else { //ANTONELLO if (hasStopTarget || hasGiveWayTarget || frenata || autoDavanti || autoDavantiFrenata) { if (targetSpeed > currentSpeed) { //serve questa condizione perchè evita di accelerare quando sono in fase di fermata targetSpeed = currentSpeed; } //currentSpeed = targetSpeed; } else { //targetSpeed -= Mathf.Min(maxBrake * Time.deltaTime, currentSpeed - targetSpeed); //Per fare in modo che arriva a targetSpeed dalla velocità corrente non troppo immediatamente targetSpeed = Mathf.MoveTowards(currentSpeed, targetSpeed, Time.fixedDeltaTime * _pidPars.velocitaFrenata); } if (targetSpeed < _pidPars.sogliaFermata) { currentSpeed = 0; } else { currentSpeed = targetSpeed; } //Debug.Log("CurrentSpeed: " + currentSpeed); //if (this.tag.Equals("Player")) //{ // Debug.Log("TargetSpeedIniziale: " + targetSpeedIniziale + "; currentSpeed impsotato: " + currentSpeed); //} } controllaAccensioneLuceStop(targetSpeedIniziale); }