using UnityEngine; using System.Collections; using System.Collections.Generic; using GameKitController.Audio; public class flyingController : vehicleController { [Header ("Custom Settings")] [Space] public float timeToFlip = 2; public float audioEngineSpeed; public float engineMinVolume = 0.5f; public float engineMaxVolume = 1; public float minAudioPitch = 0.5f; public float maxAudioPitch = 1.2f; public float maxSpeed = 30; public float velocityChangeSpeed = 10; public float stabilityForce = 2; public float stabilitySpeed = 2; public float forwardSpeed = 15; public float rightSpeed = 15; public float upSpeed = 15; public float rollRotationSpeed = 5; public float engineArmRotationAmountForward; public float engineArmRotationAmountRight; public float engineArmExtraRotationAmount; public float engineArmRotationSpeed; public float engineRotationSpeed = 10; public float groundRaycastDistance; public float hoverForce = 5; public float hoverFoeceOnAir = 2; public float rotateForce = 5; public float extraHoverSpeed = 2; public bool increaseHeightIfSurfaceBelowFound; public float raycastDistanceToCheckSurfaceBelow = 5; public float minDistanceToIncreaseHeight = 4; public Transform surfaceBelowRaycastPosition; [Space] [Header ("Vehicle Settings")] [Space] public otherVehicleParts otherCarParts; public vehicletSettings settings; [Space] [Header ("Debug")] [Space] public float heightInput; public float rollDirection; public bool groundFound; public Vector3 newVelocity; [Space] [Header ("Components")] [Space] public Transform leftEngineTransform; public Transform rightEngineTransform; public Transform leftEngineArmTransform; public Transform rightEngineArmTransform; public Transform groundRaycastPosition; float audioPower = 0; float maxEnginePower; float resetTimer; float steerInput; float forwardInput; int i; int collisionForceLimit = 5; bool rotating; Transform vehicleCameraTransform; float leftInput = 0; float rightInput = 0; bool checkVehicleTurnedOn; Vector3 currenLeftEngineArmRotation; Vector3 currenRightEngineArmRotation; Vector3 currenLeftEngineRotation; Vector3 currenRightEngineRotation; Vector3 appliedHoverForce; RaycastHit hit; bool usingRollInput; float currentHitDistance; bool surfaceDetected; bool increasingHeightFromSurfaceDetected; protected override void InitializeAudioElements () { otherCarParts.InitializeAudioElements (); } public override void Awake () { base.Awake (); } public override void Start () { base.Start (); //get the boost particles inside the vehicle for (i = 0; i < otherCarParts.boostingParticles.Count; i++) { otherCarParts.boostingParticles [i].gameObject.SetActive (false); } setAudioState (otherCarParts.engineAudioElement, 5, 0, true, false, false); setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, false, false); vehicleCameraTransform = mainVehicleCameraController.transform; } public override void vehicleUpdate () { checkCameraType (); //if the player is driving this vehicle and the gravity control is not being used, then if (driving && !usingGravityControl) { axisValues = mainInputActionManager.getPlayerMovementAxis (); if (vehicleControllerSettings.canUseBoostWithoutVerticalInput) { if (usingBoost) { axisValues.y = 1; } } horizontalAxis = axisValues.x; if (!playerMovingOn3dWorld) { horizontalAxis = 0; } rawAxisValues = mainInputActionManager.getPlayerRawMovementAxis (); if (vehicleControllerSettings.canUseBoostWithoutVerticalInput) { if (usingBoost) { rawAxisValues.y = 1; if (!playerMovingOn3dWorld) { rawAxisValues.x = 1; } } } if (!useHorizontalInputLerp && !touchPlatform) { horizontalAxis = rawAxisValues.x; if (!playerMovingOn3dWorld) { horizontalAxis = 0; } } if (mainVehicleHUDManager.usedByAI) { rollDirection = horizontalAxis; horizontalAxis = 0; } if (mainVehicleCameraController.currentState.useCameraSteer && !usingRollInput) { localLook = transform.InverseTransformDirection (mainVehicleCameraController.getLookDirection ()); if (localLook.z < 0f) { localLook.x = Mathf.Sign (localLook.x); } steering = localLook.x; steering = Mathf.Clamp (steering, -1f, 1f); steering = -steering; rollDirection = steering; } if (isTurnedOn) { //get the current values from the input manager, keyboard and touch controls verticalAxis = axisValues.y; if (!playerMovingOn3dWorld) { verticalAxis = axisValues.x; } } //if the boost input is enabled, check if there is energy enough to use it if (usingBoost) { updateMovingState (); //if there is enough energy, enable the boost if (mainVehicleHUDManager.useBoost (moving)) { boostInput = vehicleControllerSettings.maxBoostMultiplier; usingBoosting (); } //else, disable the boost else { usingBoost = false; //if the vehicle is not using the gravity control system, disable the camera move away action if (!mainVehicleGravityControl.isGravityPowerActive ()) { mainVehicleCameraController.usingBoost (false, vehicleControllerSettings.boostCameraShakeStateName, vehicleControllerSettings.useBoostCameraShake, vehicleControllerSettings.moveCameraAwayOnBoost); } usingBoosting (); boostInput = 1; } } //set the current speed in the HUD of the vehicle mainVehicleHUDManager.getSpeed (currentSpeed, maxSpeed); mainIKDrivingSystem.setNewAngularDirection (verticalAxis * Vector3.forward + horizontalAxis * Vector3.right + heightInput * Vector3.forward + rollDirection * Vector3.up); } else { //else, set the input values to 0 horizontalAxis = 0; verticalAxis = 0; rawAxisValues = Vector2.zero; } updateMovingState (); motorInput = verticalAxis; if (!playerMovingOn3dWorld) { if (motorInput < -0.01f) { motorInput *= (-1); } } //if the vehicle has fuel, allow to move it if (moving) { if (!mainVehicleHUDManager.useFuel ()) { motorInput = 0; if (isTurnedOn) { turnOnOrOff (false, isTurnedOn); } } } if (!playerMovingOn3dWorld) { update2_5DState (); } updateVehicleControllerState (); } void updateVehicleControllerState () { maxEnginePower = currentSpeed; audioPower = Mathf.Lerp (maxEnginePower, motorInput, audioEngineSpeed); otherCarParts.engineAudio.volume = Mathf.Lerp (engineMinVolume, engineMaxVolume, audioPower); otherCarParts.engineAudio.pitch = Mathf.Lerp (minAudioPitch, maxAudioPitch, audioPower); if (Mathf.Abs (horizontalAxis) > 0.05f) { steerInput = Mathf.Lerp (steerInput, horizontalAxis, Time.deltaTime * 10); } else { steerInput = Mathf.Lerp (steerInput, horizontalAxis, Time.deltaTime * 10); } if (Mathf.Abs (motorInput) > 0.05f) { forwardInput = Mathf.Lerp (forwardInput, motorInput, Time.deltaTime * 10); } else { forwardInput = Mathf.Lerp (forwardInput, motorInput, Time.deltaTime * 10); } float left = 0; float right = 0; if ((forwardInput > 0.05f || forwardInput < -0.05f) && (steerInput < 0.05f && steerInput > -0.05f)) { left = right = forwardInput; //print("moving forward or backward"); } else if (forwardInput > 0.05f && steerInput > 0) { left = forwardInput; right = -steerInput; //print("moving forward and to the right"); } else if (forwardInput > 0.05f && steerInput < 0) { left = steerInput; right = forwardInput; //print("moving forward and to the left"); } else if ((forwardInput < 0.05f && forwardInput > -0.05f) && steerInput > 0) { left = 0; right = steerInput; //print("moving to the right"); } else if ((forwardInput < 0.05f && forwardInput > -0.05f) && steerInput < 0) { left = -steerInput; right = 0; //print("moving to the left"); } else if (forwardInput < -0.05f && steerInput > 0) { left = 0; right = -steerInput; //print("moving backward and to the right"); } else if (forwardInput < -0.05f && steerInput < 0) { left = steerInput; right = 0; //print("moving backward and to the left"); } leftInput = Mathf.Lerp (leftInput, left, Time.deltaTime * 10); rightInput = Mathf.Lerp (rightInput, right, Time.deltaTime * 10); Vector3 rightHandLebarEuler = otherCarParts.rightHandLebar.transform.localEulerAngles; Vector3 lefttHandLebarEuler = otherCarParts.leftHandLebar.transform.localEulerAngles; otherCarParts.rightHandLebar.transform.localRotation = Quaternion.Euler (settings.steerAngleLimit * rightInput * 2, rightHandLebarEuler.y, rightHandLebarEuler.z); otherCarParts.leftHandLebar.transform.localRotation = Quaternion.Euler (settings.steerAngleLimit * leftInput * 2, lefttHandLebarEuler.y, lefttHandLebarEuler.z); //reset the vehicle rotation if it is upside down if (currentSpeed < 5) { //check the current rotation of the vehicle with respect to the normal of the gravity normal component, which always point the up direction float angle = Vector3.Angle (currentNormal, transform.up); if (angle > 60 && !rotating) { resetTimer += Time.deltaTime; if (resetTimer > timeToFlip) { resetTimer = 0; StartCoroutine (rotateVehicle ()); } } } } void FixedUpdate () { if (!usingGravityControl && isTurnedOn) { if (usingHoverBoardWaypoint) { return; } surfaceDetected = false; if (increaseHeightIfSurfaceBelowFound) { if (Physics.Raycast (surfaceBelowRaycastPosition.position, -transform.up, out hit, raycastDistanceToCheckSurfaceBelow, settings.layer)) { if (hit.distance < minDistanceToIncreaseHeight) { increasingHeightFromSurfaceDetected = true; inputIncreaseHeightState (true); } else { if (increasingHeightFromSurfaceDetected) { inputIncreaseHeightState (false); increasingHeightFromSurfaceDetected = false; } } } else { if (increasingHeightFromSurfaceDetected) { inputIncreaseHeightState (false); increasingHeightFromSurfaceDetected = false; } } } if (Physics.Raycast (groundRaycastPosition.position, -transform.up, out hit, groundRaycastDistance, settings.layer)) { currentHitDistance = hit.distance; surfaceDetected = true; } if (surfaceDetected) { float proportionalHeight = (groundRaycastDistance - currentHitDistance) / groundRaycastDistance; appliedHoverForce = (proportionalHeight * hoverForce) * vehicleCameraTransform.up + ((Mathf.Cos (Time.time * extraHoverSpeed)) / 2) * transform.up; mainVehicleGravityControl.setGravityForcePausedState (false); groundFound = true; } else { if (isTurnedOn) { mainVehicleGravityControl.setGravityForcePausedState (true); } else { mainVehicleGravityControl.setGravityForcePausedState (false); } groundFound = false; } if (!groundFound) { if (!moving) { appliedHoverForce = ((Mathf.Cos (Time.time * extraHoverSpeed)) / 2) * hoverFoeceOnAir * transform.up; } else { appliedHoverForce = Vector3.zero; } } if (groundFound && heightInput < 0) { heightInput = 0; } newVelocity = (motorInput * forwardSpeed) * transform.forward + (horizontalAxis * rightSpeed) * transform.right + (heightInput * upSpeed) * transform.up; newVelocity += appliedHoverForce; newVelocity *= boostInput; mainRigidbody.linearVelocity = Vector3.Lerp (mainRigidbody.linearVelocity, newVelocity, Time.deltaTime * velocityChangeSpeed); if (rollDirection != 0) { transform.Rotate (0, -rollDirection * rollRotationSpeed, 0); } Vector3 predictedUp = Quaternion.AngleAxis (mainRigidbody.angularVelocity.magnitude * Mathf.Rad2Deg * stabilityForce / stabilitySpeed, mainRigidbody.angularVelocity) * transform.up; Vector3 torqueVector = Vector3.Cross (predictedUp, vehicleCameraTransform.up); mainRigidbody.AddTorque ((stabilitySpeed * stabilitySpeed) * torqueVector); currentSpeed = mainRigidbody.linearVelocity.magnitude; currenLeftEngineArmRotation = (heightInput * engineArmRotationAmountForward) * Vector3.forward + (motorInput * engineArmRotationAmountRight) * Vector3.right - (horizontalAxis * engineArmRotationAmountForward) * Vector3.forward - (rollDirection * engineArmRotationAmountRight) * Vector3.right; currenLeftEngineArmRotation.x = Mathf.Clamp (currenLeftEngineArmRotation.x, -engineArmRotationAmountRight - engineArmExtraRotationAmount, engineArmRotationAmountRight + engineArmExtraRotationAmount); currenLeftEngineArmRotation.z = Mathf.Clamp (currenLeftEngineArmRotation.z, -engineArmRotationAmountForward - engineArmExtraRotationAmount, engineArmRotationAmountForward + engineArmExtraRotationAmount); leftEngineArmTransform.localRotation = Quaternion.Lerp (leftEngineArmTransform.localRotation, Quaternion.Euler (currenLeftEngineArmRotation), Time.deltaTime * engineArmRotationSpeed); currenRightEngineRotation = (-heightInput * engineArmRotationAmountForward) * Vector3.forward + (motorInput * engineArmRotationAmountRight) * Vector3.right - (horizontalAxis * engineArmRotationAmountForward) * Vector3.forward + (rollDirection * engineArmRotationAmountRight) * Vector3.right; currenRightEngineRotation.x = Mathf.Clamp (currenRightEngineRotation.x, -engineArmRotationAmountRight - engineArmExtraRotationAmount, engineArmRotationAmountRight + engineArmExtraRotationAmount); currenRightEngineRotation.z = Mathf.Clamp (currenRightEngineRotation.z, -engineArmRotationAmountForward - engineArmExtraRotationAmount, engineArmRotationAmountForward + engineArmExtraRotationAmount); rightEngineArmTransform.localRotation = Quaternion.Lerp (rightEngineArmTransform.localRotation, Quaternion.Euler (currenRightEngineRotation), Time.deltaTime * engineArmRotationSpeed); rightEngineTransform.Rotate (0, engineRotationSpeed * Time.deltaTime, 0); leftEngineTransform.Rotate (0, engineRotationSpeed * Time.deltaTime, 0); } if (isTurnedOn) { checkVehicleTurnedOn = true; //set the exhaust particles state for (i = 0; i < otherCarParts.normalExhaust.Count; i++) { if (isTurnedOn && currentSpeed < 20) { if (!otherCarParts.normalExhaust [i].isPlaying) { otherCarParts.normalExhaust [i].Play (); } } else { if (otherCarParts.normalExhaust [i].isPlaying) { otherCarParts.normalExhaust [i].Stop (); } } } for (i = 0; i < otherCarParts.heavyExhaust.Count; i++) { if (isTurnedOn && currentSpeed > 10 && motorInput > 0.1f) { if (!otherCarParts.heavyExhaust [i].isPlaying) { otherCarParts.heavyExhaust [i].Play (); } } else { if (otherCarParts.heavyExhaust [i].isPlaying) { otherCarParts.heavyExhaust [i].Stop (); } } } } else { if (checkVehicleTurnedOn) { stopVehicleParticles (); checkVehicleTurnedOn = false; } } } //if the vehicle is using the gravity control, set the state in this component public override void changeGravityControlUse (bool state) { base.changeGravityControlUse (state); } //the player is getting on or off from the vehicle, so public override void changeVehicleState () { base.changeVehicleState (); mainVehicleGravityControl.setGravityForcePausedState (false); } public override void setTurnOnState () { setAudioState (otherCarParts.engineAudioElement, 5, 0, true, true, false); setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, true, false); } public override void setTurnOffState (bool previouslyTurnedOn) { base.setTurnOffState (previouslyTurnedOn); if (previouslyTurnedOn) { setAudioState (otherCarParts.engineAudioElement, 5, 0, false, false, true); setAudioState (otherCarParts.engineEndAudioElement, 5, 1, false, true, false); } steerInput = 0; mainVehicleGravityControl.setGravityForcePausedState (false); } public override bool isDrivingActive () { return driving; } public override void setEngineOnOrOffState () { base.setEngineOnOrOffState (); } public override void turnOnOrOff (bool state, bool previouslyTurnedOn) { base.turnOnOrOff (state, previouslyTurnedOn); mainVehicleGravityControl.setCheckDownSpeedActiveState (!isTurnedOn); } //the vehicle has been destroyed, so disabled every component in it public override void disableVehicle () { //stop the audio sources setAudioState (otherCarParts.engineAudioElement, 5, 0, false, false, false); setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, false, false); setTurnOffState (false); //disable the exhausts particles stopVehicleParticles (); //disable the controller this.enabled = false; } public void stopVehicleParticles () { for (i = 0; i < otherCarParts.normalExhaust.Count; i++) { otherCarParts.normalExhaust [i].Stop (); } for (i = 0; i < otherCarParts.heavyExhaust.Count; i++) { otherCarParts.heavyExhaust [i].Stop (); } for (int i = 0; i < otherCarParts.boostingParticles.Count; i++) { var boostingParticlesMain = otherCarParts.boostingParticles [i].main; boostingParticlesMain.loop = false; } } //reset the vehicle rotation if it is upside down IEnumerator rotateVehicle () { rotating = true; Quaternion currentRotation = transform.rotation; //rotate in the forward direction of the vehicle Quaternion dstRotPlayer = Quaternion.LookRotation (transform.forward, currentNormal); for (float t = 0; t < 1;) { t += Time.deltaTime * 3; transform.rotation = Quaternion.Slerp (currentRotation, dstRotPlayer, t); mainRigidbody.linearVelocity = Vector3.zero; yield return null; } rotating = false; } //if the vehicle is using the boost, set the boost particles public override void usingBoosting () { base.usingBoosting (); for (int i = 0; i < otherCarParts.boostingParticles.Count; i++) { if (usingBoost) { if (!otherCarParts.boostingParticles [i].isPlaying) { otherCarParts.boostingParticles [i].gameObject.SetActive (true); otherCarParts.boostingParticles [i].Play (); var boostingParticlesMain = otherCarParts.boostingParticles [i].main; boostingParticlesMain.loop = true; } } else { if (otherCarParts.boostingParticles [i].isPlaying) { var boostingParticlesMain = otherCarParts.boostingParticles [i].main; boostingParticlesMain.loop = false; } } } } //OVERRIDE FUNCTIONS FOR VEHICLE CONTROLLER //if any collider in the vehicle collides, then public override void setCollisionDetected (Collision currentCollision) { //check that the collision is not with the player if (!currentCollision.gameObject.CompareTag ("Player")) { //if the velocity of the collision is higher that the limit if (currentCollision.relativeVelocity.magnitude > collisionForceLimit) { //set the collision audio with a random collision clip if (otherCarParts.crashAudioElements.Length > 0) { setAudioState (otherCarParts.crashAudioElements [UnityEngine.Random.Range (0, otherCarParts.crashAudioElements.Length)], 5, 1, false, true, false); } } } } public override void startBrakeVehicleToStopCompletely () { } public override void endBrakeVehicleToStopCompletely () { } public override float getCurrentSpeed () { return currentSpeed; } public override void updateMovingState () { moving = verticalAxis != 0 || horizontalAxis != 0 || heightInput != 0 || rollDirection != 0; } //CALL INPUT FUNCTIONS public override void inputHoldOrReleaseTurbo (bool holdingButton) { if (driving && !usingGravityControl && isTurnedOn && !usingHoverBoardWaypoint) { //boost input if (holdingButton) { usingBoost = true; //set the camera move away action mainVehicleCameraController.usingBoost (true, vehicleControllerSettings.boostCameraShakeStateName, vehicleControllerSettings.useBoostCameraShake, vehicleControllerSettings.moveCameraAwayOnBoost); } else { //stop boost usingBoost = false; //disable the camera move away action mainVehicleCameraController.usingBoost (false, vehicleControllerSettings.boostCameraShakeStateName, vehicleControllerSettings.useBoostCameraShake, vehicleControllerSettings.moveCameraAwayOnBoost); //disable the boost particles usingBoosting (); boostInput = 1; } } } public override void inputSetTurnOnState () { if (driving && !usingGravityControl) { if (mainVehicleHUDManager.canSetTurnOnState) { setEngineOnOrOffState (); } } } public override void inputHorn () { if (driving) { setAudioState (otherCarParts.hornAudioElement, 5, 1, false, true, false); } } public void inputIncreaseHeightState (bool state) { if (driving && !usingGravityControl && isTurnedOn) { if (state) { if (usingHoverBoardWaypoint) { pickOrReleaseHoverboardVehicle (false, false); Vector3 totalJumpForce = mainRigidbody.mass * hoverboardJumpForce * (currentNormal + transform.forward); if (useHoverboardJumpClamp) { totalJumpForce = Vector3.ClampMagnitude (totalJumpForce, hoverboardJumpClamp); } mainRigidbody.AddForce (totalJumpForce, ForceMode.Impulse); return; } } if (state) { heightInput = 1; } else { heightInput = 0; } } } public void inputDecreaseHeightState (bool state) { if (driving && !usingGravityControl && isTurnedOn) { if (state) { heightInput = -1; } else { heightInput = 0; } } } public void inputSetRotateToLeftState (bool state) { if (driving && isTurnedOn) { if (!playerMovingOn3dWorld) { rollDirection = 0; usingRollInput = false; return; } if (state) { rollDirection = 1; } else { rollDirection = 0; } usingRollInput = state; } } public void inputSetRotateToRightState (bool state) { if (driving && isTurnedOn) { if (!playerMovingOn3dWorld) { rollDirection = 0; usingRollInput = false; return; } if (state) { rollDirection = -1; } else { rollDirection = 0; } usingRollInput = state; } } [System.Serializable] public class otherVehicleParts { public Transform rightHandLebar; public Transform leftHandLebar; public Transform COM; public GameObject chassis; public AudioClip engineStartClip; public AudioElement engineStartAudioElement; public AudioClip engineClip; public AudioElement engineAudioElement; public AudioClip engineEndClip; public AudioElement engineEndAudioElement; public AudioClip[] crashClips; public AudioElement[] crashAudioElements; public AudioClip hornClip; public AudioElement hornAudioElement; public List normalExhaust = new List (); public List heavyExhaust = new List (); public AudioSource engineStartAudio; public AudioSource engineAudio; public AudioSource crashAudio; public AudioSource hornAudio; public List boostingParticles = new List (); public void InitializeAudioElements () { if (engineStartClip != null) { engineStartAudioElement.clip = engineStartClip; } if (engineClip != null) { engineAudioElement.clip = engineClip; } if (engineEndClip != null) { engineEndAudioElement.clip = engineEndClip; } if (crashClips != null && crashClips.Length > 0) { crashAudioElements = new AudioElement[crashClips.Length]; for (var i = 0; i < crashClips.Length; i++) { crashAudioElements [i] = new AudioElement { clip = crashClips [i] }; } } if (hornClip != null) { hornAudioElement.clip = hornClip; } if (engineStartAudio != null) { engineStartAudioElement.audioSource = engineStartAudio; } if (engineAudio != null) { engineAudioElement.audioSource = engineAudio; engineEndAudioElement.audioSource = engineAudio; } if (crashAudio != null) { foreach (var audioElement in crashAudioElements) { audioElement.audioSource = crashAudio; } } if (hornAudio != null) { hornAudioElement.audioSource = hornAudio; } } } [System.Serializable] public class vehicletSettings { public LayerMask layer; public float steerAngleLimit; public float increaseHeightSpeed = 2; public float decreaseHeightSpeed = 2; } }