private void processCarsWithLaneNumberAndRefernceIntersection(int laneNumber, Intersection refIntersection) { //TODO: sort list first instead of doing it on the fly AbstractCar[] sortedCars = cars .Where(c => c.position.referenceIntersection == refIntersection) .Where(c => c.position.laneNumber == laneNumber) .OrderByDescending(c => c.position.offset) .ToArray(); for (int j = 0; j < sortedCars.Length; j++) { AbstractCar car = sortedCars[j]; // check if this is the first car // TODO: Reduce code copying if (j == 0) { // move the first car into the intersection if necessary float stoppingOffset = trafficMath.stoppingDistanceForCurrentDrive(car.position); if (car.position.offset < stoppingOffset) { car.SmartAdjustSpeedAccordingToStoppingDistance(stoppingOffset - car.position.offset, 2f); car.position.offset += car.GetSpeed() * Time.deltaTime; //we should not exceed the stopping distance // If the car is close enough to the intersection if (stoppingOffset - car.position.offset < 0.05f) { car.position.offset = stoppingOffset; car.DecreaseSpeed(100f); // force stop the car moveCarToIntersection(car); } } car.updateCarPosition(); } else { // let the car follow the previous car int MIN_DIST = 2; float stoppingOffset = sortedCars[j - 1].position.offset - MIN_DIST; if (car.position.offset < stoppingOffset) { car.SmartAdjustSpeedAccordingToStoppingDistance(stoppingOffset - car.position.offset, 2f); car.position.offset += car.GetSpeed() * Time.deltaTime; } car.updateCarPosition(); } } }
public void tick() { // check if there are cars waiting to go through the intersection if (currentlyOperatingCar == null) { if (carsAtThisIntersection.Count != 0) { currentlyOperatingCar = carsAtThisIntersection [0]; carsAtThisIntersection.RemoveAt(0); // remove the car from the road // TODO: Redesign the communication between road control and intersection control trafficManager.roadControlForRoad(currentlyOperatingCar.position.referenceRoad).RemoveCarFromRoad(currentlyOperatingCar); // calculate the final form after going through the intersection Road targetRoad = navigationManager.targetWayForAbstractCarAtIntersection(currentlyOperatingCar, referenceIntersection); // get target abstract position AbstractCarPosition targetAbstractPosition = new AbstractCarPosition(targetRoad, referenceIntersection, 0, currentlyOperatingCar.position.laneNumber); float startingDistance = trafficMath.startingDistanceForCurrentDrive(targetAbstractPosition); targetAbstractPosition.offset = startingDistance; // get current and target real location currentPosition = currentlyOperatingCar.carGameObject.transform.position; currentRotation = currentlyOperatingCar.carGameObject.transform.rotation; currentlyOperatingCar.position = targetAbstractPosition; currentlyOperatingCar.CalculatePositionAndOrientation(out targetPosition, out targetRotation); // calculate the pivot Math3d.LineLineIntersection(out pivot, currentPosition, Quaternion.Euler(0, 90, 0) * currentRotation * Vector3.right, targetPosition, Quaternion.Euler(0, 90, 0) * targetRotation * Vector3.right); startTime = Time.time; } } else { // animate // very little animation if it is just a curve float turningDuration = referenceIntersection.GetGraphicsType() == Intersection.IntersectionGraphicsType.TWO_WAY_SMOOTH ? 0.1f : 1f; // end if necessary if (Time.time - startTime > turningDuration) { // we end turning and proceed to the following route RoadTrafficControl roadControl = trafficManager.roadControlForRoad(currentlyOperatingCar.position.referenceRoad); roadControl.AddCar(currentlyOperatingCar); // remember intersections is updated after roads currentlyOperatingCar.updateCarPosition(); currentlyOperatingCar = null; return; } // Slerp between positions around pivot and lerp the Quaternion rotation currentlyOperatingCar.carGameObject.transform.position = pivot + Vector3.Slerp(currentPosition - pivot, targetPosition - pivot, (Time.time - startTime) / turningDuration); currentlyOperatingCar.carGameObject.transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, (Time.time - startTime) / turningDuration); } }