/// <summary> /// On every fixed frame update, will check how the car should react to its conditions /// </summary> private void FixedUpdate() { frameCount++; /*if (gameObject.transform.parent.gameObject.name == "AICar(Clone)") * { * var player = GameObject.Find("Player"); * if (player) * { * UnityEngine.Debug.Log("Player object found"); * //float distance = Vector3.Distance(player.transform.position, gameObject.transform.position); * //UnityEngine.Debug.Log("Distance from player: " + distance); * * } * }*/ // Sleep if the round is over if (roundOver) { foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent <Rigidbody>().Sleep(); return; } // Remove AICar if at end of path if (gameObject.transform.parent.gameObject.name == "AICar(Clone)" && haveReachedDestination) { UnityEngine.Debug.Log("Destroyed Car"); GetComponent <Rigidbody>().Sleep(); Destroy(gameObject.transform.parent.gameObject); return; } //Stop movement if game timer is paused // OR if reached the end of nodes if (currentNode == -1 || (timer != null && timer.isPaused()) || haveReachedDestination) { if (haveReachedDestination && !roundOver) { sm.driverReachedDest = true; haveReachedDestination = false; } foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent <Rigidbody>().Sleep(); return; } var distanceToNode = Vector3.Distance(transform.position, nodes[currentNode].position); // If close to node if (distanceToNode < 20f && distanceToNode > 5f) { // Check if traffic light if (pathList.Count > 1 && currentNode > 0 && trafficLightController.trafficCheck(pathList[currentNode - 1], pathList[currentNode])) { if (!isAtTrafficLight) { isAtTrafficLight = true; UnityEngine.Debug.Log("Now at Traffic Light"); } foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent <Rigidbody>().Sleep(); return; } else { if (isAtTrafficLight) { UnityEngine.Debug.Log("Now no longer at Traffic Light"); } isAtTrafficLight = false; } //check for intersection and then raycast if needed if (pathList.Count > 1 && currentNode > 0 && !g.trafficLights.Contains(pathList[currentNode]) && isIntersection(pathList[currentNode]) && !isAtIntersection) { Vector3 centre = nodes[currentNode].position; bool clear = true; LayerMask layer = LayerMask.GetMask("Cars"); //check intersection is clear Collider[] hits = Physics.OverlapBox(centre, transform.localScale * 50, Quaternion.identity, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected in intersection"); foreach (Collider collider in hits) { if (collider == GetComponent <Collider>()) { continue; } var other = collider.gameObject.GetComponent <AVController>(); if (!other.isAtIntersection || !other.isAtIntersection) { continue; } Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.forward); if (dot > 0.5) // other car is travelling in same direction { continue; } else if (true) { clear = false; } } if (turning == turningDirection.left) { // check to the right hits = Physics.OverlapBox(centre + transform.right * castDistance, new Vector3(2, 1, 1) * castDistance, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected to the right when turning left."); foreach (Collider collider in hits) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) // other car is travelling left, i.e. towards this car { if (other.isAtIntersection || other.isAtTrafficLight) { continue; } // ignore cars that don't impede movement if (((int)currentBearing + 1) % 4 == (int)other.currentBearing) { UnityEngine.Debug.Log("Turning Left: Ignoring car coming from clockwise direction"); continue; } else if ((((int)currentBearing + 4) - 1) % 4 == (int)other.currentBearing && (other.turning == turningDirection.left || other.turning == turningDirection.right)) { UnityEngine.Debug.Log("Turning Left: Ignoring car coming from anti-clokwise direction turning left or right"); continue; } else if (Math.Abs(currentBearing - other.currentBearing) == 2 && (other.turning == turningDirection.left || other.turning == turningDirection.forward)) { UnityEngine.Debug.Log("Turning Left: Ignoring car coming in opposite direction going forward or turning left"); continue; } // ignore cars which give way to you if (other.braking) { continue; } // ignore cars with lower priority if (other.roadPriority < roadPriority) { continue; } if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } } else if (turning == turningDirection.forward) { // check to the right hits = Physics.OverlapBox(centre + transform.right * castDistance, new Vector3(2, 1, 1) * castDistance, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected to the right when going forward."); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); if (other.isAtIntersection || other.isAtTrafficLight) { continue; } if (other.braking) { continue; } // ignore cars with lower priority if (other.roadPriority < roadPriority) { continue; } if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check to the left hits = Physics.OverlapBox(centre - transform.right * 20, new Vector3(2, 1, 1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected to the left when going forward."); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, -transform.right); if (dot > 0) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); if (other.isAtIntersection || other.isAtTrafficLight) { continue; } if (other.braking) { continue; } if (other.roadPriority < roadPriority) { continue; } // ignore cars that don't impede movement //if (other.roadPriority == roadPriority && (other.turning == AVController.direction.forward || other.turning == AVController.direction.left)) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check forward /*hits = Physics.OverlapBox(centre + transform.forward * 5, new Vector3(1, 1, 2) * 5, transform.rotation, layer, QueryTriggerInteraction.Ignore); * foreach (Collider collider in hits) * { * Vector3 direction = collider.transform.forward; * float dot = Vector3.Dot(direction, transform.forward); * if (dot < 0) * { * if (collider == this.GetComponent<Collider>()) continue; * AVController other = collider.gameObject.GetComponent<AVController>(); * //if (other.inIntersection) continue; * * //if (other.braking) continue; * * if (currentBearing == other.currentBearing) * { * UnityEngine.Debug.Log("Going forward: Car in front going in the same direction"); * * foreach (AxleInfo axleInfo in axleInfos) * { * axleInfo.leftWheel.brakeTorque = maxMotorTorque; * axleInfo.rightWheel.brakeTorque = maxMotorTorque; * } * braking = true; * GetComponent<Rigidbody>().Sleep(); * return; * } * else * { * UnityEngine.Debug.Log("Going forward: Hitting a car so not clear"); * clear = false; * } * * * } * }*/ } else // turning right { // check to the right hits = Physics.OverlapBox(centre + transform.right * 20, new Vector3(2, 1, 1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected to the right when turning right."); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); if (other.isAtIntersection || other.isAtTrafficLight) { continue; } if (other.braking) { continue; } if (other.roadPriority < roadPriority) { continue; } // ignore cars that don't impede movement //if (other.roadPriority == roadPriority && other.turning == AVController.direction.right) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check to the left hits = Physics.OverlapBox(centre - transform.right * 20, new Vector3(2, 1, 1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected to the left when turning right."); foreach (Collider collider in hits) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); if (Math.Abs(currentBearing - other.currentBearing) == 2 && other.turning == AVController.turningDirection.right) { UnityEngine.Debug.Log("Turning Right: Ignoring car coming in opposite direction turning right"); continue; } Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, -transform.right); if (dot > 0) { if (other.isAtIntersection || other.isAtTrafficLight) { continue; } if (other.braking) { continue; } if (other.roadPriority < roadPriority) { continue; } // ignore cars that don't impede movement //if (other.roadPriority == roadPriority && other.turning == AVController.direction.right) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check forward hits = Physics.OverlapBox(centre + transform.forward * 20, new Vector3(1, 1, 2) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); UnityEngine.Debug.Log(hits.Length + " cars detected forward when turning right."); foreach (Collider collider in hits) { if (collider == this.GetComponent <Collider>()) { continue; } AVController other = collider.gameObject.GetComponent <AVController>(); if (Math.Abs(currentBearing - other.currentBearing) == 2 && other.turning == AVController.turningDirection.right) { UnityEngine.Debug.Log("Turning Right: Ignoring car coming in opposite direction turning right"); continue; } Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.forward); if (dot < 0) { if (other.isAtIntersection) { continue; } if (other.braking) { continue; } if (other.roadPriority < roadPriority) { continue; } // ignore cars that don't impede movement //if (other.roadPriority == roadPriority && other.turning == AVController.direction.right) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } } if (clear) { isAtIntersection = true; stopTime = UnityEngine.Random.Range(0f, 1f); StartCoroutine("Intersection"); } else { stopTime += 1; if (!stopped) { StartCoroutine("Stop"); } } } } //Update wheel positions based on speed and angle Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position) + new Vector3(-drivingOffset, 0, 0); float newSteer = (relativeVector.x / relativeVector.magnitude) * maxSteerAngle; foreach (AxleInfo axleInfo in axleInfos) { currentSpeed = 2 * Mathf.PI * axleInfo.leftWheel.radius * axleInfo.leftWheel.rpm * 60 / 1000; if (axleInfo.steering) { axleInfo.leftWheel.steerAngle = newSteer; axleInfo.rightWheel.steerAngle = newSteer; } if (axleInfo.motor) { if (currentSpeed < maxSpeed) { axleInfo.leftWheel.motorTorque = maxMotorTorque; axleInfo.rightWheel.motorTorque = maxMotorTorque; } else { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } } lastSpeed = currentSpeed; ApplyLocalPositionToVisuals(axleInfo.leftWheel); ApplyLocalPositionToVisuals(axleInfo.rightWheel); } if (currentSpeed == 0 && !isAtTrafficLight) { consecutiveFramesWithNoSpeed++; if (consecutiveFramesWithNoSpeed > minConsecutiveFramesWithNoSpeed) { var newFps = 1 / Time.unscaledDeltaTime; if (newFps >= 25) { fps = newFps; UnityEngine.Debug.Log("FPS:" + fps); } var consecutiveSecondsWithNoSpeed = consecutiveFramesWithNoSpeed / fps; UnityEngine.Debug.Log("Consecutive seconds with no speed:" + consecutiveSecondsWithNoSpeed); if (consecutiveSecondsWithNoSpeed >= minConsecutiveSecondsWithNoSpeed) { var randomNumber = UnityEngine.Random.Range(minConsecutiveSecondsWithNoSpeed, maxConsecutiveSecondsWithNoSpeed); if (randomNumber < consecutiveFramesWithNoSpeed) { if (nodes.Count > 1) { currentNode--; gameObject.transform.position = nodes[currentNode].position; gameObject.transform.LookAt(nodes[currentNode + 1]); gameObject.transform.position = transform.TransformPoint(new Vector3(-drivingOffset, 0, 0)); UnityEngine.Debug.Log("Have been stationary for awhile, moving back to previous node"); } consecutiveFramesWithNoSpeed = 0; } } } } else { consecutiveFramesWithNoSpeed = 0; } CheckWaypointDistance(); UpdateSteeringWheel(); }
/// <summary> /// On every fixed frame update, will check how the car should react to its conditions /// </summary> private void FixedUpdate() { // Sleep if the round is over if(roundOver) { foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent<Rigidbody>().Sleep(); return; } // Remove AICar if at end of path if (gameObject.transform.parent.gameObject.name == "AICar(Clone)" && reachedDestination) { UnityEngine.Debug.Log("Destroyed Car"); GetComponent<Rigidbody>().Sleep(); Destroy(gameObject.transform.parent.gameObject); return; } //Stop movement if game timer is paused // OR if reached the end of nodes if (currentNode == -1 || (timer != null && timer.isPaused()) || reachedDestination) { if (reachedDestination && !roundOver) { sm.driverReachedDest = true; reachedDestination = false; } foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent<Rigidbody>().Sleep(); return; } // If close to node if (Vector3.Distance(transform.position, nodes[currentNode].position) < 20f && Vector3.Distance(transform.position, nodes[currentNode].position) > 5f) { // Check if traffic light if (pathList.Count > 1 && currentNode > 0 && trafficLightController.trafficCheck(pathList[currentNode - 1], pathList[currentNode])) { //UnityEngine.Debug.Log("At Traffic Light"); foreach (AxleInfo axleInfo in axleInfos) { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } GetComponent<Rigidbody>().Sleep(); return; } //check for intersection and then raycast if needed else if (pathList.Count > 1 && currentNode > 0 && !g.trafficLights.Contains(pathList[currentNode]) && isIntersection(pathList[currentNode]) && !inIntersection) { Vector3 centre = nodes[currentNode].position; bool clear = true; LayerMask layer = LayerMask.GetMask("Cars"); //check intersection is clear Collider[] hits = Physics.OverlapBox(centre, transform.localScale * 50, Quaternion.identity, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { if (collider != this.GetComponent<Collider>()) { if (collider.gameObject.GetComponent<AVController>().inIntersection) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.forward); if (dot > 0.5) // other car is travelling in same direction { continue; } else if (true) { clear = false; } } } } if (turning == direction.left) { // check to the right hits = Physics.OverlapBox(centre + transform.right * 20, new Vector3(2,1,1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) // other car is travelling left, i.e. towards this car { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; // ignore cars which give way to you if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } } else if (turning == direction.forward) { // check to the right hits = Physics.OverlapBox(centre + transform.right * 20, new Vector3(2,1,1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check to the left hits = Physics.OverlapBox(centre - transform.right * 20, new Vector3(2,1,1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, -transform.right); if (dot > 0) { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } } else // turning right { // check to the right hits = Physics.OverlapBox(centre + transform.right * 20, new Vector3(2,1,1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.right); if (dot < 0) { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check to the left hits = Physics.OverlapBox(centre - transform.right * 20, new Vector3(2,1,1) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, -transform.right); if (dot > 0) { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } // check forward hits = Physics.OverlapBox(centre + transform.forward * 20, new Vector3(1,1,2) * 20, transform.rotation, layer, QueryTriggerInteraction.Ignore); foreach (Collider collider in hits) { Vector3 direction = collider.transform.forward; float dot = Vector3.Dot(direction, transform.forward); if (dot < 0) { if (collider == this.GetComponent<Collider>()) continue; AVController other = collider.gameObject.GetComponent<AVController>(); if (other.inIntersection) continue; if (other.braking) continue; if (other.roadPriority < roadPriority) continue; if (other.stopTime < 1 || other.stopTime > stopTime) { clear = false; } } } } if(clear) { inIntersection = true; stopTime = UnityEngine.Random.Range(0f, 1f); StartCoroutine("Intersection"); } else { stopTime += 1; if (!stopped) { StartCoroutine("Stop"); } } } } //Update wheel positions based on speed and angle Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position) + new Vector3(-drivingOffset, 0, 0); float newSteer = (relativeVector.x / relativeVector.magnitude) * maxSteerAngle; foreach (AxleInfo axleInfo in axleInfos) { currentSpeed = 2 * Mathf.PI * axleInfo.leftWheel.radius * axleInfo.leftWheel.rpm * 60 / 1000; if (axleInfo.steering) { axleInfo.leftWheel.steerAngle = newSteer; axleInfo.rightWheel.steerAngle = newSteer; } if (axleInfo.motor) { if (currentSpeed < maxSpeed) { axleInfo.leftWheel.motorTorque = maxMotorTorque; axleInfo.rightWheel.motorTorque = maxMotorTorque; } else { axleInfo.leftWheel.motorTorque = 0; axleInfo.rightWheel.motorTorque = 0; } } ApplyLocalPositionToVisuals(axleInfo.leftWheel); ApplyLocalPositionToVisuals(axleInfo.rightWheel); } CheckWaypointDistance(); UpdateSteeringWheel(); }