using Gley.TrafficSystem.Internal; using Gley.UrbanSystem.Internal; using System.Collections.Generic; using UnityEngine; namespace Gley.TrafficSystem { public class DefaultDelegates { #region VehicleBehaviours public static void PlayerInTriggerBehaviour(int vehicleIndex, Collider player) { API.AddDrivingAction(vehicleIndex, DriveActions.Follow, false); } public static void DynamicObstacleInTriggerBehaviour(int vehicleIndex, Collider obstacle) { API.AddDrivingAction(vehicleIndex, DriveActions.StopInDistance, false); } public static void BuildingInTriggerBehaviour(int vehicleIndex, Collider building) { API.AddDrivingAction(vehicleIndex, DriveActions.AvoidReverse, false); } /// /// Called when 2 vehicles hit each other /// /// /// /// if false resume driving, else check possibilities public static void VehicleCrashBehaviour(int vehicleIndex, ObstacleTypes obstacleType, Collider other) { //Debug.Log("VehicleCrashHandler " + obstacleType, other); switch (obstacleType) { case ObstacleTypes.Player: API.AddDrivingAction(vehicleIndex, DriveActions.StopTemp, false); break; case ObstacleTypes.Road: break; case ObstacleTypes.TrafficVehicle: API.AddDrivingAction(vehicleIndex, GetCrashAction(vehicleIndex, other), false); break; default: API.AddDrivingAction(vehicleIndex, DriveActions.StopTemp, false); break; } } private static DriveActions GetCrashAction(int myIndex, Collider other) { #if GLEY_TRAFFIC_SYSTEM var vehiclePositioningSystem = TrafficManager.Instance.VehiclePositioningSystem; var trafficVehicles = TrafficManager.Instance.AllVehiclesDataHandler; int otherIndex = other.attachedRigidbody.GetComponent().ListIndex; //determine relative position and moving directions int inFront = vehiclePositioningSystem.IsInFront(myIndex, otherIndex); bool sameOrientation = vehiclePositioningSystem.IsSameOrientation(trafficVehicles.GetHeading(myIndex), trafficVehicles.GetHeading(otherIndex)); bool sameHeading = vehiclePositioningSystem.IsSameHeading(trafficVehicles.GetForwardVector(otherIndex), trafficVehicles.GetForwardVector(myIndex)); bool goingForward = vehiclePositioningSystem.IsGoingForward(trafficVehicles.GetVelocity(myIndex), trafficVehicles.GetHeading(myIndex)); if (inFront == 2) { //I am behind if (goingForward == true) { //I am going forward if (sameOrientation == true) { //the other vehicle is oriented forward if (sameHeading == true) { //other vehicle is going forward //-> I have hit him from behind so I should stop return DriveActions.StopTemp; } else { //if other vehicle is going in reverse i should also return DriveActions.Reverse; } } else { //I am on the wrong way -> reverse return DriveActions.Reverse; } } else { //I am going backwards so I should stop because I hit something return DriveActions.StopTemp; } } else { if (inFront == 1) { //I am in front if (goingForward == true) { // I am going forward if (sameOrientation == false) { // I am on the wrong way and I hit something -> reverse return DriveActions.Reverse; } else { //something hit me from behind, continue return DriveActions.Forward; } } else { //I am going backwards and I hit something -> stop return DriveActions.StopTemp; } } else { //it is not clear who is in front if (sameHeading) { //if we are going in the same direction I should stop //return DriveActions.StopTemp; return DriveActions.Forward; } else { //I am on the wrong way -> reverse return DriveActions.Reverse; } } } #else return default; #endif } #endregion #region SpawnWaypoints /// /// The default behavior, a random square is chosen from the available ones /// /// /// /// /// public static int GetRandomSpawnWaypoint(List neighbors, Vector3 position, Vector3 direction, VehicleTypes vehicleType, bool useWaypointPriority) { #if GLEY_TRAFFIC_SYSTEM Vector2Int selectedNeighbor = neighbors[Random.Range(0, neighbors.Count)]; return GetPossibleWaypoint(selectedNeighbor, vehicleType, useWaypointPriority); #else return -1; #endif } /// /// The square in front of the player is chosen /// /// /// /// /// public static int GetForwardSpawnWaypoint(List neighbors, Vector3 position, Vector3 direction, VehicleTypes vehicleType, bool useWaypointPriority) { #if GLEY_TRAFFIC_SYSTEM Vector2Int selectedNeighbor = Vector2Int.zero; float angle = 180; for (int i = 0; i < neighbors.Count; i++) { Vector3 cellDirection = API.GetGridDataHandler().GetCellPosition(neighbors[i]) - position; float newAngle = Vector3.Angle(cellDirection, direction); if (newAngle < angle) { selectedNeighbor = neighbors[i]; angle = newAngle; } } return GetPossibleWaypoint(selectedNeighbor, vehicleType, useWaypointPriority); #else return -1; #endif } private static int GetPossibleWaypoint(Vector2Int selectedNeighbor, VehicleTypes vehicleType, bool usePriority) { #if GLEY_TRAFFIC_SYSTEM ////get a random waypoint that supports the current vehicle List possibleWaypoints = API.GetGridDataHandler().GetTrafficSpawnWaypointsForCell(selectedNeighbor, (int)vehicleType); if (possibleWaypoints.Count > 0) { if (usePriority) { int totalPriority = 0; foreach (SpawnWaypoint waypoint in possibleWaypoints) { totalPriority += waypoint.Priority; } int randomPriority = Random.Range(1, totalPriority); totalPriority = 0; for (int i = 0; i < possibleWaypoints.Count; i++) { totalPriority += possibleWaypoints[i].Priority; if (totalPriority >= randomPriority) { return possibleWaypoints[i].WaypointIndex; } } } else { return possibleWaypoints[Random.Range(0, possibleWaypoints.Count)].WaypointIndex; } } #endif return -1; } #endregion #region TrafficLights public static void TrafficLightBehaviour(TrafficLightsColor currentRoadColor, GameObject[] redLightObjects, GameObject[] yellowLightObjects, GameObject[] greenLightObjects, string name) { switch (currentRoadColor) { case TrafficLightsColor.Red: SetLight(true, redLightObjects, name); SetLight(false, yellowLightObjects, name); SetLight(false, greenLightObjects, name); break; case TrafficLightsColor.YellowRed: case TrafficLightsColor.YellowGreen: SetLight(false, redLightObjects, name); SetLight(true, yellowLightObjects, name); SetLight(false, greenLightObjects, name); break; case TrafficLightsColor.Green: SetLight(false, redLightObjects, name); SetLight(false, yellowLightObjects, name); SetLight(true, greenLightObjects, name); break; } } /// /// Set traffic lights color /// private static void SetLight(bool active, GameObject[] lightObjects, string name) { for (int j = 0; j < lightObjects.Length; j++) { if (lightObjects[j] != null) { if (lightObjects[j].activeSelf != active) { lightObjects[j].SetActive(active); } } else { Debug.LogWarning("Intersection " + name + " has null red light objects"); } } } #endregion #region TriggerModifier public static void TriggerSizeModifier(float currentSpeed, BoxCollider frontCollider, float maxSpeed, float minTriggerLength, float maxTriggerLength) { float minSpeed = 20; if (currentSpeed < minSpeed) { frontCollider.size = new Vector3(frontCollider.size.x, frontCollider.size.y, minTriggerLength); frontCollider.center = new Vector3(frontCollider.center.x, frontCollider.center.y, minTriggerLength / 2); } else { if (currentSpeed >= maxSpeed) { frontCollider.size = new Vector3(frontCollider.size.x, frontCollider.size.y, maxTriggerLength); frontCollider.center = new Vector3(frontCollider.center.x, frontCollider.center.y, maxTriggerLength / 2); } else { float newsize = minTriggerLength + (currentSpeed - minSpeed) * ((maxTriggerLength - minTriggerLength) / (maxSpeed - minSpeed)); frontCollider.size = new Vector3(frontCollider.size.x, frontCollider.size.y, newsize); frontCollider.center = new Vector3(frontCollider.center.x, frontCollider.center.y, newsize / 2); } } } #endregion } }