plantilla base para movimiento básico
This commit is contained in:
Robii Aragon
2026-02-05 05:07:55 -08:00
parent 195b696771
commit 779f2c8b20
14443 changed files with 23840465 additions and 452 deletions

View File

@@ -0,0 +1,830 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using GameKitController.Audio;
public class hoverCraftController : vehicleController
{
[Header ("Custom Settings")]
[Space]
public float maxSteeringTorque = 1400;
public float rollOnTurns = 10;
public float rollOnTurnsTorque = 20;
public float steerBrakingTorque = 1400;
public float brakingTorque;
public float pitchCompensationTorque;
public float rollCompensationTorque = 10;
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 maxForwardAcceleration = 20;
public float maxReverseAcceleration = 15;
public float maxBrakingDeceleration = 30;
public float autoBrakingDeceleration;
public float maxSpeed = 30;
public AnimationCurve accelerationCurve;
public float verticalReduction = 10;
public float maxPitchAngle = 45;
public Vector3 extraRigidbodyForce;
public float minSteerInputIdle = 0.4f;
public float minSteerInputMoving = 0.4f;
[Space]
[Header ("Hovercraft Settings")]
[Space]
public List<hoverEngineSettings> hoverEngineList = new List<hoverEngineSettings> ();
public OtherCarParts otherCarParts;
public hoverCraftSettings settings;
[Space]
[Header ("Debug")]
[Space]
public bool anyOnGround;
float audioPower = 0;
float maxEnginePower;
float resetTimer;
float steerInput;
float forwardInput;
float originalJumpPower;
int i;
int collisionForceLimit = 5;
bool rotating;
float leftInput = 0;
float rightInput = 0;
float currentMinSteerInput;
hoverEngineSettings currentEngine;
int hoverEngineListCount;
ParticleSystem currentParticleSystem;
protected override void InitializeAudioElements ()
{
otherCarParts.InitializeAudioElements ();
}
public override void Awake ()
{
base.Awake ();
}
public override void Start ()
{
base.Start ();
hoverEngineListCount = hoverEngineList.Count;
//get the boost particles inside the vehicle
for (i = 0; i < otherCarParts.boostingParticles.Count; i++) {
if (otherCarParts.boostingParticles [i].gameObject.activeSelf) {
otherCarParts.boostingParticles [i].gameObject.SetActive (false);
}
}
for (i = 0; i < hoverEngineList.Count; i++) {
currentEngine = hoverEngineList [i];
currentEngine.hasTurbine = currentEngine.turbine != null;
currentEngine.hasParticles = currentEngine.ParticleSystem != null;
}
setAudioState (otherCarParts.engineAudioElement, 5, 0, true, false, false);
setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, false, false);
originalJumpPower = vehicleControllerSettings.jumpPower;
}
public override void vehicleUpdate ()
{
base.vehicleUpdate ();
maxEnginePower = 0;
for (i = 0; i < hoverEngineListCount; i++) {
currentEngine = hoverEngineList [i];
if (currentEngine.maxEnginePower > maxEnginePower) {
maxEnginePower = currentEngine.maxEnginePower;
}
//configure every particle system according to the engine state
float rpm = Mathf.Lerp (currentEngine.minRPM, currentEngine.maxRPM, currentEngine.maxEnginePower);
if (currentEngine.hasTurbine) {
currentEngine.turbine.transform.Rotate (0, rpm * Time.deltaTime * 6, 0);
}
if (currentEngine.hasParticles) {
var hoverEngineParticleEmission = currentEngine.ParticleSystem.emission;
hoverEngineParticleEmission.rateOverTime = currentEngine.maxEmission * currentEngine.maxEnginePower;
currentEngine.ParticleSystem.transform.position =
currentEngine.hit.point + currentEngine.dustHeight * currentEngine.hit.normal;
currentEngine.ParticleSystem.transform.LookAt (currentEngine.hit.point + 10 * currentEngine.hit.normal);
}
}
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 ()
{
currentSpeed = mainRigidbody.linearVelocity.magnitude;
if (usingHoverBoardWaypoint) {
return;
}
//apply turn
if (Mathf.Approximately (horizontalAxis, 0)) {
float localR = Vector3.Dot (mainRigidbody.angularVelocity, transform.up);
mainRigidbody.AddRelativeTorque (0, -localR * steerBrakingTorque, 0);
} else {
float targetRoll = -rollOnTurns * horizontalAxis;
float roll = Mathf.Asin (transform.right.y) * Mathf.Rad2Deg;
if (Mathf.Abs (roll) > Mathf.Abs (targetRoll)) {
roll = 0;
} else {
roll = Mathf.DeltaAngle (roll, targetRoll);
}
mainRigidbody.AddRelativeTorque (0, horizontalAxis * maxSteeringTorque, roll * rollOnTurnsTorque);
}
if (!usingGravityControl && !jumpInputPressed) {
Vector3 localVelocity = transform.InverseTransformDirection (mainRigidbody.linearVelocity);
Vector3 extraForce = Vector3.Scale (localVelocity, extraRigidbodyForce);
mainRigidbody.AddRelativeForce (mainRigidbody.mass * (-extraForce));
Vector3 gravityForce = (9.8f * currentNormal).normalized;
//use every engine to keep the vehicle in the air
for (i = 0; i < hoverEngineListCount; i++) {
currentEngine = hoverEngineList [i];
//if the current engine is the main engine
if (!currentEngine.mainEngine) {
//find force direction by rotating local up vector towards world up
Vector3 engineUp = currentEngine.engineTransform.up;
Vector3 enginePosition = currentEngine.engineTransform.position;
engineUp = Vector3.RotateTowards (engineUp, gravityForce, currentEngine.maxEngineAngle * Mathf.Deg2Rad, 1);
//check if the vehicle is on ground
currentEngine.maxEnginePower = 0;
if (Physics.Raycast (enginePosition, -engineUp, out currentEngine.hit, currentEngine.maxHeight, settings.layer)) {
//calculate down force
currentEngine.maxEnginePower = Mathf.Pow ((currentEngine.maxHeight - currentEngine.hit.distance) / currentEngine.maxHeight, currentEngine.Exponent);
float force = currentEngine.maxEnginePower * currentEngine.engineForce;
float velocityUp = Vector3.Dot (mainRigidbody.GetPointVelocity (enginePosition), engineUp);
float drag = -velocityUp * Mathf.Abs (velocityUp) * currentEngine.damping;
mainRigidbody.AddForceAtPosition ((force + drag) * engineUp, enginePosition);
}
} else {
//find current local pitch and roll
float pitch = Mathf.Asin (Vector3.Dot (transform.forward, gravityForce)) * Mathf.Rad2Deg;
float roll = Mathf.Asin (Vector3.Dot (transform.right, gravityForce)) * Mathf.Rad2Deg;
pitch = Mathf.DeltaAngle (pitch, 0);
roll = Mathf.DeltaAngle (roll, 0);
//apply compensation torque
float auxPitch = -pitch * pitchCompensationTorque;
float auxRoll = roll * rollCompensationTorque;
if (!anyOnGround) {
auxPitch *= 0.5f;
auxRoll *= 0.5f;
}
mainRigidbody.AddRelativeTorque (pitch, 0, auxRoll);
}
}
bool brakeActive = (braking || isBrakeActive ());
if (brakeActive) {
float localR = Vector3.Dot (mainRigidbody.angularVelocity, transform.up);
mainRigidbody.AddRelativeTorque (0, -localR * brakingTorque, 0);
for (i = 0; i < hoverEngineListCount; i++) {
currentEngine = hoverEngineList [i];
if (currentEngine.mainEngine) {
mainRigidbody.linearVelocity = Vector3.Lerp (mainRigidbody.linearVelocity, Vector3.zero, Time.deltaTime);
}
}
} else {
for (i = 0; i < hoverEngineListCount; i++) {
currentEngine = hoverEngineList [i];
if (currentEngine.mainEngine) {
float movementMultiplier = settings.inAirMovementMultiplier;
if (Physics.Raycast (currentEngine.engineTransform.position, -transform.up, out currentEngine.hit, currentEngine.maxHeight, settings.layer)) {
movementMultiplier = 1;
}
//current speed along forward axis
float speed = Vector3.Dot (mainRigidbody.linearVelocity, transform.forward);
//if the vehicle doesn't move by input, apply automatic brake
bool isAutoBraking = Mathf.Approximately (motorInput, 0) && autoBrakingDeceleration > 0;
float thrust = motorInput;
if (isAutoBraking) {
thrust = -Mathf.Sign (speed) * autoBrakingDeceleration / maxBrakingDeceleration;
}
//check if it is braking, for example speed and thrust have opposing signs
bool isBraking = speed * motorInput < 0;
//don't apply force if speed is max already
if (Mathf.Abs (speed) < maxSpeed || isBraking) {
//position on speed curve
float normSpeed = Mathf.Sign (motorInput) * speed / maxSpeed;
//apply acceleration curve and select proper maximum value
float acc = accelerationCurve.Evaluate (normSpeed) * (isBraking ? maxBrakingDeceleration : thrust > 0 ? maxForwardAcceleration : maxReverseAcceleration);
//drag should be added to the acceleration
float sdd = speed * extraRigidbodyForce.z;
float dragForce = sdd + mainRigidbody.linearDamping * speed;
float force = acc * thrust + dragForce;
//reduce acceleration if the vehicle is close to vertical orientation and is trrying to go higher
float y = Vector3.Dot (transform.forward, gravityForce);
if (maxPitchAngle < 90 && y * thrust > 0) {
if (!isAutoBraking) {
float pitch2 = Mathf.Asin (Mathf.Abs (y)) * Mathf.Rad2Deg;
if (pitch2 > maxPitchAngle) {
float reduction = (pitch2 - maxPitchAngle) / (90 - maxPitchAngle) * verticalReduction;
force /= 1 + reduction;
}
}
}
mainRigidbody.AddForce ((boostInput * movementMultiplier * force) * transform.forward, ForceMode.Acceleration);
}
}
}
}
}
//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 ();
}
}
}
anyOnGround = true;
int totalWheelsOnAir = 0;
for (i = 0; i < hoverEngineListCount; i++) {
currentEngine = hoverEngineList [i];
if (!Physics.Raycast (currentEngine.engineTransform.position, -currentEngine.engineTransform.up, out currentEngine.hit,
currentEngine.maxHeight, settings.layer)) {
totalWheelsOnAir++;
}
}
//if the total amount of wheels in the air is equal to the number of wheel sin the vehicle, anyOnGround is false
if (totalWheelsOnAir == hoverEngineListCount && anyOnGround) {
anyOnGround = false;
}
}
IEnumerator jumpCoroutine ()
{
jumpInputPressed = true;
yield return new WaitForSeconds (0.5f);
jumpInputPressed = false;
}
public override void updateCameraSteerState ()
{
if (localLook.z < 0f) {
localLook.x = Mathf.Sign (localLook.x);
}
steering = localLook.x;
steering = Mathf.Clamp (steering, -1f, 1f);
if (axisValues.y != 0) {
currentMinSteerInput = minSteerInputMoving;
} else {
currentMinSteerInput = minSteerInputIdle;
}
if (Mathf.Abs (steering) > currentMinSteerInput) {
horizontalAxis = steering;
} else {
horizontalAxis = 0;
}
}
//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 ();
}
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;
}
public override bool isDrivingActive ()
{
return driving;
}
public override void setEngineOnOrOffState ()
{
base.setEngineOnOrOffState ();
}
public override void turnOnOrOff (bool state, bool previouslyTurnedOn)
{
base.turnOnOrOff (state, previouslyTurnedOn);
}
//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
for (i = 0; i < otherCarParts.normalExhaust.Count; i++) {
otherCarParts.normalExhaust [i].Stop ();
}
for (i = 0; i < otherCarParts.heavyExhaust.Count; i++) {
otherCarParts.heavyExhaust [i].Stop ();
}
//disable the controller
this.enabled = 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++) {
currentParticleSystem = otherCarParts.boostingParticles [i];
if (usingBoost) {
if (!currentParticleSystem.isPlaying) {
if (!currentParticleSystem.gameObject.activeSelf) {
currentParticleSystem.gameObject.SetActive (true);
}
currentParticleSystem.Play ();
var boostingParticlesMain = currentParticleSystem.main;
boostingParticlesMain.loop = true;
}
} else {
if (currentParticleSystem.isPlaying) {
var boostingParticlesMain = currentParticleSystem.main;
boostingParticlesMain.loop = false;
}
}
}
}
//use a jump platform
public void useVehicleJumpPlatform (Vector3 direction)
{
StartCoroutine (jumpCoroutine ());
mainRigidbody.AddForce (mainRigidbody.mass * direction, ForceMode.Impulse);
}
public void useJumpPlatformParable (Vector3 direction)
{
Vector3 jumpForce = direction;
mainRigidbody.AddForce (jumpForce, ForceMode.VelocityChange);
}
public void setNewJumpPower (float newJumpPower)
{
vehicleControllerSettings.jumpPower = newJumpPower * 100;
}
public void setOriginalJumpPower ()
{
vehicleControllerSettings.jumpPower = originalJumpPower;
}
public void setCanJumpState (bool state)
{
vehicleControllerSettings.canJump = state;
}
//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 ()
{
braking = true;
}
public override void endBrakeVehicleToStopCompletely ()
{
braking = false;
}
public override float getCurrentSpeed ()
{
return currentSpeed;
}
//CALL INPUT FUNCTIONS
public override void inputJump ()
{
if (driving && !usingGravityControl && isTurnedOn && vehicleControllerSettings.canJump) {
if (anyOnGround && !jumpInputPressed) {
StartCoroutine (jumpCoroutine ());
mainRigidbody.AddForce (mainRigidbody.mass * vehicleControllerSettings.jumpPower * currentNormal, ForceMode.Impulse);
}
if (usingHoverBoardWaypoint) {
StartCoroutine (jumpCoroutine ());
pickOrReleaseHoverboardVehicle (false, false);
Vector3 totalJumpForce = mainRigidbody.mass * hoverboardJumpForce * (currentNormal + transform.forward);
if (useHoverboardJumpClamp) {
totalJumpForce = Vector3.ClampMagnitude (totalJumpForce, hoverboardJumpClamp);
}
mainRigidbody.AddForce (totalJumpForce, ForceMode.Impulse);
}
}
}
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 override void inputHoldOrReleaseBrake (bool holdingButton)
{
if (driving && !usingGravityControl) {
braking = holdingButton;
}
}
[System.Serializable]
public class hoverEngineSettings
{
public string Name;
public Transform engineTransform;
public ParticleSystem ParticleSystem;
public float maxEmission = 250;
public float dustHeight = 0.1f;
public float maxHeight = 2;
public float engineForce = 4000;
public float damping = 150;
public float Exponent = 2;
public float maxEngineAngle = 10;
public bool mainEngine;
public float minRPM = 100;
public float maxRPM = 150;
public Transform turbine;
[HideInInspector] public RaycastHit hit;
[HideInInspector] public float maxEnginePower;
[HideInInspector] public bool hasTurbine;
[HideInInspector] public bool hasParticles;
}
[System.Serializable]
public class OtherCarParts
{
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<ParticleSystem> normalExhaust = new List<ParticleSystem> ();
public List<ParticleSystem> heavyExhaust = new List<ParticleSystem> ();
public AudioSource engineStartAudio;
public AudioSource engineAudio;
public AudioSource crashAudio;
public AudioSource hornAudio;
public List<ParticleSystem> boostingParticles = new List<ParticleSystem> ();
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 hoverCraftSettings
{
public LayerMask layer;
public float steerAngleLimit;
[Range (0, 1)] public float inAirMovementMultiplier;
}
}