//Fires when no longer colliding with another collider
    private void OnTriggerExit(Collider other)
    {
        //Trains don't collide with anything
        if (VehicleType == TrafficType.Train)
        {
            return;
        }

        if (other.transform.tag == "Bridge")
        {
            StartCoroutine(DisableCrossedBridgeBool());
        }

        if (other.transform.tag == "Track")
        {
            StartCoroutine(DisableCrossedTrackBool());
        }

        if (CollidesWithTags.Contains(other.transform.tag))
        {
            isBehindOtherVehicle = false;
            otherVehicle         = null;
            hasPriority          = false;
        }
    }
    //Returns true if not waiting for red light and not in front of another vehicle (or if this vehicle has movement priority over other vehicle)
    private bool PathIsClear()
    {
        isInFrontOfRedLight = TrafficLightIsRed();
        if (trafficLightBarrier != null && !isInFrontOfRedLight)
        {
            //No longer waiting for red light
            trafficLightBarrier = null;
        }

        //Other vehicle disappeared
        if (otherVehicle = null)
        {
            isBehindOtherVehicle = false;
        }

        if (isInFrontOfOpenBridge)
        {
            if (waitingForBridge.state == DeckState.Closed)
            {
                isInFrontOfOpenBridge = false;
            }
        }

        return(!isInFrontOfRedLight && !isInFrontOfOpenBridge && (!isBehindOtherVehicle || hasPriority));
    }
    //Fires when colliding with another collider
    private void OnTriggerEnter(Collider other)
    {
        //Calculate the dotproduct between transform and target transform. (used for finding out how the target unit is facing us)
        float dotForward = Vector3.Dot(other.transform.forward, transform.forward);

        //Traffic light in-sight
        if (other.transform.tag == "Trafficlight_Barrier")
        {
            //If train and barrier is facing the other way, ignore it...
            if (VehicleType == TrafficType.Train && dotForward > -0.8f)
            {
                return;
            }

            //Barrier is facing this unit the opposite way & unit is crossing bridge or track, ignore opposing barrier..
            else if (isCrossingBridgeOrTrack && dotForward > 0.8f)
            {
                return;
            }

            //Pedestrian or Cyclist has just crossed the road and is facing a red light barrier on the opposite side. Ignore it..
            else if ((VehicleType == TrafficType.Bicycle || VehicleType == TrafficType.Pedestrian) && other.GetComponentInParent <Trafficlight>() != null && dotForward > 0.8f)
            {
                return;
            }

            //Barrier is facing this unit at an angle. The barrier is probably not meant for this unit, ignore it..
            else if (dotForward > -0.8f && dotForward < 0.8f)
            {
                return;
            }

            Trafficlight_Barrier barrier = other.GetComponent <Trafficlight_Barrier>();
            if (barrier.IsActive) //(trafficlight_barrier is only active when trafficlight is red)
            {
                isInFrontOfRedLight = true;
                trafficLightBarrier = barrier;
            }
        }

        //Stop when bridge is closed
        if (other.transform.tag == "Bridge" && VehicleType != TrafficType.Boat)
        {
            Bridge bridge = other.GetComponent <Bridge>();
            isCrossingBridgeOrTrack = true;
            if (bridge.state == DeckState.Open)
            {
                isInFrontOfOpenBridge = true;
                waitingForBridge      = bridge;
            }
        }

        if (other.transform.tag == "Track" && VehicleType != TrafficType.Train)
        {
            isCrossingBridgeOrTrack = true;
        }

        //In front of other (waiting) vehicle
        if (CollidesWithTags.Contains(other.transform.tag))
        {
            //Other unit is facing this unit almost head on. Move through target unit.
            //(Implementing rerouting for cyclists/pedestrians when facing target unit is too complicated)
            if (VehicleType == TrafficType.Bicycle || VehicleType == TrafficType.Pedestrian)
            {
                if (dotForward < -0.6f)
                {
                    return;
                }
            }

            isBehindOtherVehicle = true;
            otherVehicle         = other.GetComponentInParent <WaypointMovementController>();

            //If the other vehicle also collides with this vehicle, give this one priority to move first
            if (otherVehicle.otherVehicle == this)
            {
                if (!otherVehicle.hasPriority)
                {
                    hasPriority = true;
                }
            }
        }
    }
    void SpawnVehicle(TrafficType type)
    {
        int     randomIndex   = -1;
        Spawner randomSpawner = null;
        WaypointMovementController spawnedVehicle = null;

        switch (type)
        {
        case TrafficType.Car:
            //Spawn car at random Spawner position
            randomIndex   = UnityEngine.Random.Range(0, CarSpawners.Length);
            randomSpawner = CarSpawners[randomIndex];
            if (randomSpawner.Object.GetComponent <Spawn>().PositionIsOccupied)
            {
                //Spawner position is already occupied by another unit, don't spawn.
                return;
            }
            spawnedVehicle = Instantiate(CarPrefab, randomSpawner.Object.transform.position, Quaternion.identity).GetComponent <WaypointMovementController>();
            spawnedVehicle.transform.parent = CarParent.transform;
            spawnedVehicle.spawnLocation    = randomSpawner.Location;
            break;

        case TrafficType.Train:
            //Spawn train at random Spawner position
            randomIndex   = UnityEngine.Random.Range(0, TrainSpawners.Length);
            randomSpawner = TrainSpawners[randomIndex];
            if (randomSpawner.Object.GetComponent <Spawn>().PositionIsOccupied)
            {
                //Spawner position is already occupied by another unit, don't spawn.
                return;
            }
            spawnedVehicle = Instantiate(TrainPrefab, randomSpawner.Object.transform.position, Quaternion.identity).GetComponent <WaypointMovementController>();
            spawnedVehicle.transform.parent = TrainParent.transform;
            spawnedVehicle.spawnLocation    = randomSpawner.Location;
            break;

        case TrafficType.Boat:
            //Spawn boat at random Spawner position
            randomIndex   = UnityEngine.Random.Range(0, BoatSpawners.Length);
            randomSpawner = BoatSpawners[randomIndex];
            if (randomSpawner.Object.GetComponent <Spawn>().PositionIsOccupied)
            {
                //Spawner position is already occupied by another unit, don't spawn.
                return;
            }
            spawnedVehicle = Instantiate(BoatPrefab, randomSpawner.Object.transform.position, Quaternion.identity).GetComponent <WaypointMovementController>();
            spawnedVehicle.transform.parent = BoatParent.transform;
            spawnedVehicle.spawnLocation    = randomSpawner.Location;
            break;

        case TrafficType.Bicycle:
            //Spawn cyclist at random Spawner position
            randomIndex   = UnityEngine.Random.Range(0, CyclistSpawners.Length);
            randomSpawner = CyclistSpawners[randomIndex];
            if (randomSpawner.Object.GetComponent <Spawn>().PositionIsOccupied)
            {
                //Spawner position is already occupied by another unit, don't spawn.
                return;
            }
            spawnedVehicle = Instantiate(CyclistPrefab, randomSpawner.Object.transform.position, Quaternion.identity).GetComponent <WaypointMovementController>();
            spawnedVehicle.transform.parent = CyclistParent.transform;
            spawnedVehicle.spawnLocation    = randomSpawner.Location;
            break;

        case TrafficType.Pedestrian:
            //Spawn pedestrian at random Spawner position
            randomIndex   = UnityEngine.Random.Range(0, PedestrianSpawners.Length);
            randomSpawner = PedestrianSpawners[randomIndex];
            if (randomSpawner.Object.GetComponent <Spawn>().PositionIsOccupied)
            {
                //Spawner position is already occupied by another unit, don't spawn.
                return;
            }
            spawnedVehicle = Instantiate(PedestrianPrefab, randomSpawner.Object.transform.position, Quaternion.identity).GetComponent <WaypointMovementController>();
            spawnedVehicle.transform.parent = PedestrianParent.transform;
            spawnedVehicle.spawnLocation    = randomSpawner.Location;
            break;
        }
    }