// Traffic Simulation // https://github.com/mchrbn/unity-traffic-simulation using System.Collections.Generic; using UnityEngine; namespace TrafficSimulation{ public enum IntersectionType{ STOP, TRAFFIC_LIGHT } public class Intersection : MonoBehaviour { public IntersectionType intersectionType; public int id; //For stop only public List prioritySegments; //For traffic lights only public float lightsDuration = 8; public float orangeLightDuration = 2; public List lightsNbr1; public List lightsNbr2; private List vehiclesQueue; private List vehiclesInIntersection; private TrafficSystem trafficSystem; [HideInInspector] public int currentRedLightsGroup = 1; void Start(){ vehiclesQueue = new List(); vehiclesInIntersection = new List(); if(intersectionType == IntersectionType.TRAFFIC_LIGHT) InvokeRepeating("SwitchLights", lightsDuration, lightsDuration); } void SwitchLights(){ if(currentRedLightsGroup == 1) currentRedLightsGroup = 2; else if(currentRedLightsGroup == 2) currentRedLightsGroup = 1; //Wait few seconds after light transition before making the other car move (= orange light) Invoke("MoveVehiclesQueue", orangeLightDuration); } void OnTriggerEnter(Collider _other) { //Check if vehicle is already in the list if yes abort //Also abort if we just started the scene (if vehicles inside colliders at start) if(IsAlreadyInIntersection(_other.gameObject) || Time.timeSinceLevelLoad < .5f) return; if(_other.tag == "AutonomousVehicle" && intersectionType == IntersectionType.STOP){ //Debug.Log("Trigger Stop!"); TriggerStop(_other.gameObject); }else if(_other.tag == "AutonomousVehicle" && intersectionType == IntersectionType.TRAFFIC_LIGHT){ //Debug.Log("Trigger Light!"); TriggerLight(_other.gameObject); } } void OnTriggerExit(Collider _other) { if(_other.tag == "AutonomousVehicle" && intersectionType == IntersectionType.STOP) ExitStop(_other.gameObject); else if(_other.tag == "AutonomousVehicle" && intersectionType == IntersectionType.TRAFFIC_LIGHT) ExitLight(_other.gameObject); } void TriggerStop(GameObject _vehicle){ VehicleAI vehicleAI = _vehicle.GetComponent(); //Depending on the waypoint threshold, the car can be either on the target segment or on the past segment int vehicleSegment = vehicleAI.GetSegmentVehicleIsIn(); if(!IsPrioritySegment(vehicleSegment)){ if(vehiclesQueue.Count > 0 || vehiclesInIntersection.Count > 0){ vehicleAI.vehicleStatus = Status.STOP; vehiclesQueue.Add(_vehicle); } else{ vehiclesInIntersection.Add(_vehicle); vehicleAI.vehicleStatus = Status.SLOW_DOWN; } } else{ vehicleAI.vehicleStatus = Status.SLOW_DOWN; vehiclesInIntersection.Add(_vehicle); } } void ExitStop(GameObject _vehicle){ _vehicle.GetComponent().vehicleStatus = Status.GO; vehiclesInIntersection.Remove(_vehicle); vehiclesQueue.Remove(_vehicle); if(vehiclesQueue.Count > 0 && vehiclesInIntersection.Count == 0){ vehiclesQueue[0].GetComponent().vehicleStatus = Status.GO; } } void TriggerLight(GameObject _vehicle){ VehicleAI vehicleAI = _vehicle.GetComponent(); int vehicleSegment = vehicleAI.GetSegmentVehicleIsIn(); if(IsRedLightSegment(vehicleSegment)){ //Debug.Log("Stop Vehicle"); vehicleAI.vehicleStatus = Status.STOP; vehiclesQueue.Add(_vehicle); } else{ //Debug.Log("Go Vehicle"); vehicleAI.vehicleStatus = Status.GO; } } void ExitLight(GameObject _vehicle){ _vehicle.GetComponent().vehicleStatus = Status.GO; } bool IsRedLightSegment(int _vehicleSegment){ if(currentRedLightsGroup == 1){ foreach(Segment segment in lightsNbr1){ if(segment.id == _vehicleSegment) return true; } } else{ foreach(Segment segment in lightsNbr2){ if(segment.id == _vehicleSegment) return true; } } return false; } void MoveVehiclesQueue(){ //Move all vehicles in queue List nVehiclesQueue = new List(vehiclesQueue); foreach(GameObject vehicle in vehiclesQueue){ int vehicleSegment = vehicle.GetComponent().GetSegmentVehicleIsIn(); if(!IsRedLightSegment(vehicleSegment)){ vehicle.GetComponent().vehicleStatus = Status.GO; nVehiclesQueue.Remove(vehicle); } } vehiclesQueue = nVehiclesQueue; } bool IsPrioritySegment(int _vehicleSegment){ foreach(Segment s in prioritySegments){ if(_vehicleSegment == s.id) return true; } return false; } bool IsAlreadyInIntersection(GameObject _target){ foreach(GameObject vehicle in vehiclesInIntersection){ if(vehicle.GetInstanceID() == _target.GetInstanceID()) return true; } foreach(GameObject vehicle in vehiclesQueue){ if(vehicle.GetInstanceID() == _target.GetInstanceID()) return true; } return false; } private List memVehiclesQueue = new List(); private List memVehiclesInIntersection = new List(); public void SaveIntersectionStatus(){ memVehiclesQueue = vehiclesQueue; memVehiclesInIntersection = vehiclesInIntersection; } public void ResumeIntersectionStatus(){ foreach(GameObject v in vehiclesInIntersection){ foreach(GameObject v2 in memVehiclesInIntersection){ if(v.GetInstanceID() == v2.GetInstanceID()){ v.GetComponent().vehicleStatus = v2.GetComponent().vehicleStatus; break; } } } foreach(GameObject v in vehiclesQueue){ foreach(GameObject v2 in memVehiclesQueue){ if(v.GetInstanceID() == v2.GetInstanceID()){ v.GetComponent().vehicleStatus = v2.GetComponent().vehicleStatus; break; } } } } } }