123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- // 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<Segment> prioritySegments;
- //For traffic lights only
- public float lightsDuration = 8;
- public float orangeLightDuration = 2;
- public List<Segment> lightsNbr1;
- public List<Segment> lightsNbr2;
- private List<GameObject> vehiclesQueue;
- private List<GameObject> vehiclesInIntersection;
- private TrafficSystem trafficSystem;
-
- [HideInInspector] public int currentRedLightsGroup = 1;
- void Start(){
- vehiclesQueue = new List<GameObject>();
- vehiclesInIntersection = new List<GameObject>();
- 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<VehicleAI>();
-
- //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<VehicleAI>().vehicleStatus = Status.GO;
- vehiclesInIntersection.Remove(_vehicle);
- vehiclesQueue.Remove(_vehicle);
- if(vehiclesQueue.Count > 0 && vehiclesInIntersection.Count == 0){
- vehiclesQueue[0].GetComponent<VehicleAI>().vehicleStatus = Status.GO;
- }
- }
- void TriggerLight(GameObject _vehicle){
- VehicleAI vehicleAI = _vehicle.GetComponent<VehicleAI>();
- 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<VehicleAI>().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<GameObject> nVehiclesQueue = new List<GameObject>(vehiclesQueue);
- foreach(GameObject vehicle in vehiclesQueue){
- int vehicleSegment = vehicle.GetComponent<VehicleAI>().GetSegmentVehicleIsIn();
- if(!IsRedLightSegment(vehicleSegment)){
- vehicle.GetComponent<VehicleAI>().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<GameObject> memVehiclesQueue = new List<GameObject>();
- private List<GameObject> memVehiclesInIntersection = new List<GameObject>();
- 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<VehicleAI>().vehicleStatus = v2.GetComponent<VehicleAI>().vehicleStatus;
- break;
- }
- }
- }
- foreach(GameObject v in vehiclesQueue){
- foreach(GameObject v2 in memVehiclesQueue){
- if(v.GetInstanceID() == v2.GetInstanceID()){
- v.GetComponent<VehicleAI>().vehicleStatus = v2.GetComponent<VehicleAI>().vehicleStatus;
- break;
- }
- }
- }
- }
- }
- }
|