1636 lines
56 KiB
C#
1636 lines
56 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using GameKitController.Audio;
|
|
|
|
public class carController : vehicleController
|
|
{
|
|
[Header ("Custom Settings")]
|
|
[Space]
|
|
|
|
public List<Wheels> wheelsList = new List<Wheels> ();
|
|
public List<Gears> gearsList = new List<Gears> ();
|
|
public OtherCarParts otherCarParts;
|
|
public carSettings settings;
|
|
|
|
public bool rotateVehicleUpward = true;
|
|
|
|
public float minInclinationToRotateVehicle = 60;
|
|
|
|
public float rotateVehicleUpwardSpeed = 3;
|
|
|
|
public bool bounceVehicleOnPassengerGettingOnOff;
|
|
|
|
[Space]
|
|
[Header ("Debug")]
|
|
[Space]
|
|
|
|
public int currentGear;
|
|
|
|
public float currentRearRPM = 0;
|
|
public float currentRPM = 0;
|
|
public bool anyOnGround;
|
|
|
|
public bool externalBrakeActive;
|
|
|
|
public bool reversing;
|
|
|
|
public bool pauseAutoRotationActiveState;
|
|
|
|
[Space]
|
|
[Header ("Components")]
|
|
[Space]
|
|
|
|
public skidsManager skidMarksManager;
|
|
public shipInterfaceInfo interfaceInfo;
|
|
|
|
|
|
List<ParticleSystem> boostingParticles = new List<ParticleSystem> ();
|
|
|
|
|
|
bool colliding;
|
|
bool rotating;
|
|
|
|
int i, j;
|
|
int collisionForceLimit = 5;
|
|
float horizontalLean = 0;
|
|
float verticalLean = 0;
|
|
float resetTimer = 0;
|
|
|
|
float steerInput = 0;
|
|
|
|
float acceleration;
|
|
float lastVelocity = 0;
|
|
float defSteerAngle;
|
|
float driftAngle;
|
|
float timeToStabilize = 0;
|
|
|
|
float currentTimeStabilizing = 0;
|
|
|
|
float originalJumpPower;
|
|
RaycastHit hit;
|
|
|
|
bool interfaceActive;
|
|
|
|
bool bouncingVehicle;
|
|
Coroutine bounceCoroutine;
|
|
|
|
Transform currentWheelColliderTransform;
|
|
|
|
WheelCollider currentWheelCollider;
|
|
|
|
Transform currentWheelMesh;
|
|
Transform currentMudGuard;
|
|
Transform currentSuspension;
|
|
|
|
Wheels currentWheel;
|
|
|
|
Quaternion currentWheelColliderRotation;
|
|
|
|
float localScaleY;
|
|
|
|
WheelHit wheelGroundHitFront = new WheelHit ();
|
|
WheelHit wheelGroundHitRear = new WheelHit ();
|
|
|
|
WheelHit FrontWheelHit;
|
|
WheelHit RearWheelHit;
|
|
|
|
float currentSteerInput;
|
|
|
|
Vector3 newLocalEulerAngles;
|
|
|
|
Vector3 vector3Zero = Vector3.zero;
|
|
|
|
Vector3 currentWheelColliderLocalEulerAngles;
|
|
float currentWheelColliderZAxisAngle;
|
|
|
|
float currentSteeringWheelZAxisAngle;
|
|
|
|
Vector3 wheelCenterPosition;
|
|
|
|
bool currentHasMudGuardValue;
|
|
bool currentHasSuspensionValue;
|
|
|
|
Vector3 currentWheelUp;
|
|
|
|
float currentWheelRadius;
|
|
float currentWheelSuspensionDistance;
|
|
|
|
RaycastHit [] raycastResults = new RaycastHit [1];
|
|
|
|
int hitsAmount;
|
|
|
|
float currentSkidsVolume;
|
|
|
|
int wheelsListCount;
|
|
|
|
int gearListCount;
|
|
|
|
ParticleSystem currentParticleSystem;
|
|
|
|
protected override void InitializeAudioElements ()
|
|
{
|
|
otherCarParts.InitializeAudioElements ();
|
|
|
|
foreach (var gear in gearsList) {
|
|
gear.InitializeAudioElements ();
|
|
|
|
if (otherCarParts.gearShiftingSound != null) {
|
|
gear.gearShiftingAudioElement.audioSource = otherCarParts.gearShiftingSound;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Awake ()
|
|
{
|
|
base.Awake ();
|
|
|
|
}
|
|
|
|
public override void Start ()
|
|
{
|
|
base.Start ();
|
|
|
|
//get every wheel component, like the mudguard, suspension and the slip smoke particles
|
|
wheelsListCount = wheelsList.Count;
|
|
|
|
gearListCount = gearsList.Count;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheel.hasMudGuard = currentWheel.mudGuard != null;
|
|
|
|
if (currentWheel.hasMudGuard) {
|
|
currentMudGuard = currentWheel.mudGuard.transform;
|
|
|
|
currentWheel.mudGuardOriginalLocalEuler = transform.localEulerAngles;
|
|
currentWheel.mudGuardOffset = currentMudGuard.localPosition - currentWheel.wheelMesh.transform.localPosition;
|
|
}
|
|
|
|
currentWheel.hasSuspension = currentWheel.suspension != null;
|
|
|
|
if (currentWheel.hasSuspension) {
|
|
currentSuspension = currentWheel.suspension.transform;
|
|
|
|
currentWheel.suspensionOffset = currentSuspension.localPosition - currentWheel.wheelMesh.transform.localPosition;
|
|
}
|
|
|
|
currentWheel.hasParticles = currentWheel.wheelParticleSystem != null;
|
|
}
|
|
|
|
//set the sound components
|
|
setAudioState (otherCarParts.engineAudioElement, 5, 0, true, false, false);
|
|
setAudioState (otherCarParts.skidAudioElement, 5, 0, true, false, false);
|
|
setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, false, false);
|
|
|
|
//get the vehicle rigidbody
|
|
mainRigidbody.maxAngularVelocity = 5;
|
|
|
|
//store the max sterr angle
|
|
defSteerAngle = settings.steerAngleLimit;
|
|
|
|
//get the boost particles inside the vehicle
|
|
if (otherCarParts.boostParticles) {
|
|
Component [] boostParticlesComponents = otherCarParts.boostParticles.GetComponentsInChildren (typeof (ParticleSystem));
|
|
foreach (ParticleSystem child in boostParticlesComponents) {
|
|
boostingParticles.Add (child);
|
|
|
|
child.gameObject.SetActive (false);
|
|
}
|
|
}
|
|
|
|
originalJumpPower = vehicleControllerSettings.jumpPower;
|
|
}
|
|
|
|
public override void vehicleUpdate ()
|
|
{
|
|
base.vehicleUpdate ();
|
|
|
|
//set the current axis input in the motor input
|
|
currentRearRPM = 0;
|
|
|
|
float currentDeltaTime = Time.deltaTime;
|
|
|
|
//steering input
|
|
steerInput = Mathf.Lerp (steerInput, horizontalAxis, currentDeltaTime * settings.steerInputSpeed);
|
|
|
|
currentSteerInput = settings.steerAngleLimit * steerInput;
|
|
|
|
//set the steer angle in every steerable wheel and get the currentRearRPM from the wheel that power the vehicle
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
if (currentWheel.steerable) {
|
|
if (currentWheel.reverseSteer) {
|
|
currentWheelCollider.steerAngle = -currentSteerInput;
|
|
} else {
|
|
currentWheelCollider.steerAngle = currentSteerInput;
|
|
}
|
|
}
|
|
|
|
if (currentWheel.powered) {
|
|
currentRearRPM += currentWheelCollider.rpm;
|
|
}
|
|
}
|
|
|
|
//change gears
|
|
if (!changingGear && !usingGravityControl) {
|
|
if (currentGear + 1 < gearListCount) {
|
|
if (currentSpeed >= gearsList [currentGear].gearSpeed && currentRearRPM > 0) {
|
|
//print ("mas"+gearsList [currentGear+1].Name + " " + gearsList [currentGear].gearSpeed);
|
|
StartCoroutine (changeGear (currentGear + 1));
|
|
}
|
|
}
|
|
|
|
if (currentGear - 1 >= 0) {
|
|
if (currentSpeed < gearsList [currentGear - 1].gearSpeed) {
|
|
//print ("menos"+gearsList [currentGear-1].Name + " " + gearsList [currentGear-1].gearSpeed);
|
|
StartCoroutine (changeGear (currentGear - 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
//reset the vehicle rotation if it is upside down
|
|
if (isUseOfGravityActive () && 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);
|
|
|
|
//&& !colliding
|
|
if (angle > minInclinationToRotateVehicle && !rotating) {
|
|
resetTimer += currentDeltaTime;
|
|
|
|
if (resetTimer > 1.5f) {
|
|
resetTimer = 0;
|
|
|
|
if (rotateVehicleUpward && !pauseAutoRotationActiveState) {
|
|
rotateVehicle ();
|
|
}
|
|
}
|
|
}
|
|
|
|
//set the current gear to 0
|
|
if (currentGear > 0) {
|
|
StartCoroutine (changeGear (0));
|
|
}
|
|
}
|
|
|
|
//if the vehicle has a steering Wheel, rotate it according to the steer input
|
|
if (otherCarParts.SteeringWheel != null) {
|
|
currentSteeringWheelZAxisAngle = -settings.steerAngleLimit * steerInput + (driftAngle / settings.steeringAssistanceDivider) * 2;
|
|
|
|
if (Mathf.Abs (currentSteeringWheelZAxisAngle) > 0.01f) {
|
|
|
|
otherCarParts.SteeringWheel.localEulerAngles =
|
|
new Vector3 (otherCarParts.SteeringWheel.localEulerAngles.x, otherCarParts.SteeringWheel.localEulerAngles.y, currentSteeringWheelZAxisAngle);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FixedUpdate ()
|
|
{
|
|
if (usingHoverBoardWaypoint) {
|
|
return;
|
|
}
|
|
|
|
float currentDeltaTime = Time.deltaTime;
|
|
|
|
localScaleY = transform.localScale.y;
|
|
|
|
//check every wheel collider of the vehicle, to move it and apply rotation to it correctly using raycast
|
|
WheelHit wheelGroundHit = new WheelHit ();
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
//get the center position of the wheel
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelColliderTransform = currentWheelCollider.transform;
|
|
|
|
currentWheelMesh = currentWheel.wheelMesh.transform;
|
|
|
|
currentHasMudGuardValue = currentWheel.hasMudGuard;
|
|
|
|
if (currentHasMudGuardValue) {
|
|
currentMudGuard = currentWheel.mudGuard.transform;
|
|
}
|
|
|
|
currentHasSuspensionValue = currentWheel.hasSuspension;
|
|
|
|
if (currentHasSuspensionValue) {
|
|
currentSuspension = currentWheel.suspension.transform;
|
|
}
|
|
|
|
currentWheelRadius = currentWheelCollider.radius;
|
|
|
|
currentWheelSuspensionDistance = currentWheelCollider.suspensionDistance;
|
|
|
|
wheelCenterPosition = currentWheelColliderTransform.TransformPoint (currentWheelCollider.center);
|
|
|
|
//use a raycast in the ground direction
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHit);
|
|
|
|
currentWheelUp = currentWheelColliderTransform.up;
|
|
|
|
//if the wheel is close enough to the ground, then
|
|
hitsAmount = Physics.RaycastNonAlloc (wheelCenterPosition, -currentWheelUp, raycastResults,
|
|
(currentWheelSuspensionDistance + currentWheelRadius) * localScaleY, settings.layer);
|
|
|
|
if (hitsAmount > 0) {
|
|
//set the wheel mesh position according to the values of the wheel collider
|
|
currentWheelMesh.position = raycastResults [0].point + (currentWheelRadius * localScaleY) * currentWheelUp;
|
|
|
|
//set the suspension spring position of the wheel collider
|
|
currentWheel.suspensionSpringPos = -(raycastResults [0].distance - currentWheelRadius);
|
|
}
|
|
|
|
//the wheel is in the air
|
|
else {
|
|
//set the suspension spring position of the wheel collider
|
|
currentWheel.suspensionSpringPos = -currentWheelSuspensionDistance;
|
|
|
|
//set the wheel mesh position according to the values of the wheel collider
|
|
currentWheelMesh.position = wheelCenterPosition - (currentWheelSuspensionDistance * localScaleY) * currentWheelUp;
|
|
}
|
|
|
|
//set the rotation value in the wheel collider
|
|
currentWheel.rotationValue += currentWheelCollider.rpm * (6) * currentDeltaTime;
|
|
|
|
currentWheelColliderRotation = currentWheelColliderTransform.rotation;
|
|
|
|
//if the wheel powers the vehicle
|
|
if (currentWheel.powered) {
|
|
//rotate the wheel mesh only according to the current speed
|
|
currentWheelMesh.rotation = currentWheelColliderRotation * Quaternion.Euler (currentWheel.rotationValue, 0, currentWheelColliderRotation.z);
|
|
}
|
|
|
|
//if the wheel is used to change the vehicle direction
|
|
if (currentWheel.steerable) {
|
|
//rotate the wheel mesh according to the current speed and rotate in the local Y axis according to the rotation of the steering wheel
|
|
currentWheelMesh.rotation = currentWheelColliderRotation * Quaternion.Euler (currentWheel.rotationValue,
|
|
currentWheelCollider.steerAngle + (driftAngle / settings.steeringAssistanceDivider), currentWheelColliderRotation.z);
|
|
}
|
|
|
|
//if the wheel has a mudguard
|
|
if (currentHasMudGuardValue) {
|
|
if (currentWheel.steerable) {
|
|
newLocalEulerAngles = currentWheel.mudGuardOriginalLocalEuler + new Vector3 (0, settings.steerAngleLimit * steerInput, 0);
|
|
|
|
//if the wheel is steerable, rotate the mudguard according to that rotation
|
|
if (!newLocalEulerAngles.Equals (vector3Zero)) {
|
|
currentMudGuard.localEulerAngles = newLocalEulerAngles;
|
|
}
|
|
}
|
|
|
|
//set its position according to the wheel position
|
|
currentMudGuard.localPosition = currentWheelMesh.localPosition + currentWheel.mudGuardOffset;
|
|
}
|
|
|
|
//if the wheel has suspension, set its poition just like the mudguard
|
|
if (currentHasSuspensionValue) {
|
|
currentSuspension.localPosition = currentWheel.suspensionOffset + currentWheelMesh.localPosition;
|
|
}
|
|
|
|
//calculate the drift angle, using the right side of the vehicle
|
|
if (currentWheel.powered && currentWheel.rightSide) {
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHit);
|
|
driftAngle = Mathf.Lerp (driftAngle, (Mathf.Clamp (wheelGroundHit.sidewaysSlip, settings.driftAngleLimit.x, settings.driftAngleLimit.y)), currentDeltaTime * 2);
|
|
}
|
|
|
|
//rotate the wheel collider in its forward local axis
|
|
float handling = Mathf.Lerp (-1, 1, wheelGroundHit.force / settings.steerWheelRotationPercentage);
|
|
|
|
int mult = 1;
|
|
|
|
if (currentWheel.leftSide) {
|
|
mult = -1;
|
|
}
|
|
|
|
currentWheelColliderZAxisAngle = (handling * mult);
|
|
|
|
if (Mathf.Abs (currentWheel.lastWheelColliderRotationValue - currentWheelColliderZAxisAngle) > 0.01f) {
|
|
currentWheel.lastWheelColliderRotationValue = currentWheelColliderZAxisAngle;
|
|
|
|
currentWheelColliderLocalEulerAngles = currentWheelColliderTransform.localEulerAngles;
|
|
|
|
currentWheelColliderTransform.localEulerAngles =
|
|
new Vector3 (currentWheelColliderLocalEulerAngles.x, currentWheelColliderLocalEulerAngles.y, currentWheelColliderZAxisAngle);
|
|
}
|
|
|
|
//check the right front and right rear wheel to play the skid audio according to their state
|
|
|
|
//use a wheel hit to that
|
|
if (currentWheel.powered && currentWheel.rightSide) {
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHitFront);
|
|
}
|
|
|
|
if (currentWheel.steerable && currentWheel.rightSide) {
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHitRear);
|
|
}
|
|
}
|
|
|
|
currentSkidsVolume = otherCarParts.skidAudio.volume;
|
|
|
|
if (anyOnGround) {
|
|
//if the values in the wheel hit are higher that
|
|
if (Mathf.Abs (wheelGroundHitFront.sidewaysSlip) > 0.25f || Mathf.Abs (wheelGroundHitRear.forwardSlip) > 0.5f || Mathf.Abs (wheelGroundHitFront.forwardSlip) > 0.5f) {
|
|
//and the vehicle is moving, then
|
|
if (mainRigidbody.linearVelocity.magnitude > 1) {
|
|
//set the skid volume value according to the vehicle skid
|
|
currentSkidsVolume = Mathf.Abs (wheelGroundHitFront.sidewaysSlip) + ((Mathf.Abs (wheelGroundHitFront.forwardSlip) +
|
|
Mathf.Abs (wheelGroundHitRear.forwardSlip)) / 4f);
|
|
} else {
|
|
//set the skid volume value to 0
|
|
currentSkidsVolume -= currentDeltaTime;
|
|
}
|
|
} else {
|
|
//set the skid volume value to 0
|
|
currentSkidsVolume -= currentDeltaTime;
|
|
}
|
|
} else {
|
|
currentSkidsVolume -= currentDeltaTime * 10;
|
|
}
|
|
|
|
otherCarParts.skidAudio.volume = currentSkidsVolume;
|
|
|
|
//rotate the vehicle chassis when the gear is being changed
|
|
//get the vertical lean value
|
|
verticalLean = Mathf.Clamp (Mathf.Lerp (verticalLean, mainRigidbody.angularVelocity.x * settings.chassisLean.y, currentDeltaTime * 3),
|
|
-settings.chassisLeanLimit, settings.chassisLeanLimit);
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered && currentWheel.rightSide) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHit);
|
|
}
|
|
}
|
|
|
|
float normalizedLeanAngle = Mathf.Clamp (wheelGroundHit.sidewaysSlip, -1, 1);
|
|
|
|
if (normalizedLeanAngle > 0) {
|
|
normalizedLeanAngle = 1;
|
|
} else {
|
|
normalizedLeanAngle = -1;
|
|
}
|
|
|
|
if (!bouncingVehicle) {
|
|
//get the horizontal lean value
|
|
horizontalLean = Mathf.Clamp (Mathf.Lerp (horizontalLean,
|
|
(Mathf.Abs (transform.InverseTransformDirection (mainRigidbody.angularVelocity).y) * -normalizedLeanAngle) * settings.chassisLean.x, currentDeltaTime * 3),
|
|
-settings.chassisLeanLimit, settings.chassisLeanLimit);
|
|
|
|
Quaternion chassisRotation = Quaternion.Euler (verticalLean, otherCarParts.chassis.transform.localRotation.y + (mainRigidbody.angularVelocity.z), horizontalLean);
|
|
|
|
Vector3 targetLocalEulerAngles = chassisRotation.eulerAngles;
|
|
|
|
//set the lean rotation value in the chassis transform
|
|
if (Mathf.Abs (targetLocalEulerAngles.magnitude) > 0.01f) {
|
|
if (!float.IsNaN (targetLocalEulerAngles.x) && !float.IsNaN (targetLocalEulerAngles.y) && !float.IsNaN (targetLocalEulerAngles.z)) {
|
|
otherCarParts.chassis.transform.localEulerAngles = targetLocalEulerAngles;
|
|
}
|
|
}
|
|
|
|
//set the vehicle mass center
|
|
mainRigidbody.centerOfMass = new Vector3 ((otherCarParts.COM.localPosition.x) * transform.localScale.x,
|
|
(otherCarParts.COM.localPosition.y) * localScaleY, (otherCarParts.COM.localPosition.z) * transform.localScale.z);
|
|
}
|
|
|
|
//allows vehicle to remain roughly pointing in the direction of travel
|
|
//if the vehicle is not on the ground, not colliding, rotating and its speed is higher that 5
|
|
if (!anyOnGround && settings.preserveDirectionWhileInAir && !colliding && !rotating && currentSpeed > 5 && !pauseAutoRotationActiveState) {
|
|
//check the time to stabilize
|
|
if (timeToStabilize < settings.minTimeToPreserveDirectionWhileInAir) {
|
|
timeToStabilize += currentDeltaTime;
|
|
} else {
|
|
bool rotateVehicleResult = true;
|
|
|
|
if (settings.useMaxTimeToPreserveDirectionWhileOnAir) {
|
|
currentTimeStabilizing += currentDeltaTime;
|
|
|
|
if (currentTimeStabilizing >= settings.maxTimeToPreserveDirectionWhileOnAir) {
|
|
rotateVehicleResult = false;
|
|
}
|
|
}
|
|
|
|
if (rotateVehicleResult) {
|
|
//rotate every axis of the vehicle in the rigidbody velocity direction
|
|
mainRigidbody.freezeRotation = true;
|
|
|
|
float angleX = Mathf.Asin (transform.InverseTransformDirection (Vector3.Cross (currentNormal.normalized, transform.up)).x) * Mathf.Rad2Deg;
|
|
float angleZ = Mathf.Asin (transform.InverseTransformDirection (Vector3.Cross (currentNormal.normalized, transform.up)).z) * Mathf.Rad2Deg;
|
|
float angleY = Mathf.Asin (transform.InverseTransformDirection (Vector3.Cross (mainRigidbody.linearVelocity.normalized, transform.forward)).y) * Mathf.Rad2Deg;
|
|
|
|
transform.Rotate ((currentDeltaTime * -1) * new Vector3 (angleX, angleY, angleZ));
|
|
}
|
|
}
|
|
}
|
|
|
|
//if any of the vehicle is on the groud, free the rigidbody rotation
|
|
if (anyOnGround) {
|
|
mainRigidbody.freezeRotation = false;
|
|
timeToStabilize = 0;
|
|
|
|
currentTimeStabilizing = 0;
|
|
}
|
|
|
|
bool brakeActive = (braking || isBrakeActive ());
|
|
|
|
//if the handbrake is pressed, set the brake torque value in every wheel
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
if (brakeActive) {
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider.brakeTorque = settings.brake * 15;
|
|
}
|
|
|
|
if (currentWheel.steerable) {
|
|
if (settings.useBrakeValueOnSteerableWheels) {
|
|
currentWheelCollider.brakeTorque = settings.brakeValueOnSteerableWheels * 15;
|
|
} else {
|
|
currentWheelCollider.brakeTorque = settings.brake / 10;
|
|
}
|
|
}
|
|
} else {
|
|
//else, check if the vehicle input is in forward or in backward direction
|
|
|
|
//the vehicle is decelerating
|
|
if (Mathf.Abs (motorInput) <= 0.05f && !changingGear) {
|
|
currentWheelCollider.brakeTorque = settings.brake / 25;
|
|
}
|
|
|
|
//the vehicle is braking
|
|
else if (motorInput < 0 && !reversing) {
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider.brakeTorque = settings.brake * (Mathf.Abs (motorInput / 2));
|
|
}
|
|
|
|
if (currentWheel.steerable) {
|
|
currentWheelCollider.brakeTorque = settings.brake * (Mathf.Abs (motorInput));
|
|
}
|
|
} else {
|
|
currentWheelCollider.brakeTorque = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//adhere the vehicle to the ground
|
|
//check the front part
|
|
float travel = 1;
|
|
float totalTravel = 0;
|
|
float antiRollForceFront;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.steerable) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
//if the wheel is in the ground
|
|
bool grounded = currentWheelCollider.GetGroundHit (out FrontWheelHit);
|
|
|
|
if (grounded) {
|
|
//get the value to the ground according to the wheel collider configuration
|
|
travel = (-currentWheelCollider.transform.InverseTransformPoint (FrontWheelHit.point).y - currentWheelCollider.radius) /
|
|
currentWheelCollider.suspensionDistance;
|
|
}
|
|
|
|
//if the wheel is the front wheel
|
|
if (currentWheel.leftSide) {
|
|
//add to the total travel
|
|
totalTravel += travel;
|
|
}
|
|
|
|
//else
|
|
if (currentWheel.rightSide) {
|
|
//substract from the total travel
|
|
totalTravel -= travel;
|
|
}
|
|
}
|
|
|
|
travel = 1;
|
|
}
|
|
|
|
bool anyWheelOnGroundOnFront = false;
|
|
|
|
//now, with the force multiplier which has to be applied in the front wheels
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.steerable) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
int mult = 1;
|
|
|
|
if (currentWheel.leftSide) {
|
|
mult = -1;
|
|
}
|
|
|
|
//get the total amount of force applied to every wheel
|
|
antiRollForceFront = totalTravel * settings.antiRoll;
|
|
|
|
//if the wheel is on the ground, apply the force
|
|
bool grounded = currentWheelCollider.GetGroundHit (out FrontWheelHit);
|
|
|
|
if (grounded) {
|
|
mainRigidbody.AddForceAtPosition ((mult * antiRollForceFront) * currentWheelCollider.transform.up, currentWheelCollider.transform.position);
|
|
|
|
anyWheelOnGroundOnFront = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//like the above code, but this time in the rear wheels
|
|
bool groundRear = true;
|
|
|
|
travel = 1;
|
|
totalTravel = 0;
|
|
float antiRollForceRear = 0;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
bool grounded = currentWheelCollider.GetGroundHit (out RearWheelHit);
|
|
|
|
if (grounded) {
|
|
travel = (-currentWheelCollider.transform.InverseTransformPoint (RearWheelHit.point).y - currentWheelCollider.radius) /
|
|
|
|
currentWheelCollider.suspensionDistance;
|
|
}
|
|
|
|
if (currentWheel.leftSide) {
|
|
totalTravel += travel;
|
|
}
|
|
|
|
if (currentWheel.rightSide) {
|
|
totalTravel -= travel;
|
|
}
|
|
}
|
|
|
|
travel = 1;
|
|
}
|
|
|
|
bool anyWheelOnGroundOnRear = false;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
int mult = 1;
|
|
|
|
if (currentWheel.leftSide) {
|
|
mult = -1;
|
|
}
|
|
|
|
antiRollForceRear = totalTravel * settings.antiRoll;
|
|
|
|
bool grounded = currentWheelCollider.GetGroundHit (out RearWheelHit);
|
|
|
|
if (grounded) {
|
|
mainRigidbody.AddForceAtPosition ((mult * antiRollForceRear) * currentWheelCollider.transform.up, currentWheelCollider.transform.position);
|
|
|
|
anyWheelOnGroundOnRear = true;
|
|
}
|
|
//if both rear wheels are not in the ground, then
|
|
else {
|
|
groundRear = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//if both rear wheels are in the ground, then
|
|
if (groundRear) {
|
|
//add an extra force to the main rigidbody of the vehicle
|
|
mainRigidbody.AddRelativeTorque ((steerInput * 5000) * Vector3.up);
|
|
}
|
|
|
|
if (anyWheelOnGroundOnRear || anyWheelOnGroundOnFront) {
|
|
//check if the jump input has been presses
|
|
if (jumpInputPressed) {
|
|
//apply force in the up direction
|
|
mainRigidbody.AddForce ((mainRigidbody.mass * vehicleControllerSettings.jumpPower) * transform.up);
|
|
|
|
jumpInputPressed = false;
|
|
|
|
lastTimeJump = Time.time;
|
|
}
|
|
}
|
|
|
|
//get the current speed value
|
|
currentSpeed = mainRigidbody.linearVelocity.magnitude * 3;
|
|
|
|
//calculate the current acceleration
|
|
acceleration = 0;
|
|
acceleration = (transform.InverseTransformDirection (mainRigidbody.linearVelocity).z - lastVelocity) / Time.fixedDeltaTime;
|
|
lastVelocity = transform.InverseTransformDirection (mainRigidbody.linearVelocity).z;
|
|
|
|
//set the drag according to vehicle acceleration
|
|
mainRigidbody.linearDamping = Mathf.Clamp ((acceleration / 50), 0, 1);
|
|
|
|
//set the steer limit
|
|
settings.steerAngleLimit = Mathf.Lerp (defSteerAngle, settings.highSpeedSteerAngle, (currentSpeed / settings.highSpeedSteerAngleAtSpeed));
|
|
|
|
//set the current RPM
|
|
|
|
float nextRPM = ((Mathf.Abs (currentRearRPM) * settings.gearShiftRate) + settings.minRPM) /
|
|
(currentGear + 1);
|
|
|
|
currentRPM = Mathf.Clamp (nextRPM,
|
|
settings.minRPM,
|
|
settings.maxRPM);
|
|
|
|
//check if the vehicle is moving forwards or backwards
|
|
if (motorInput <= 0 && currentRearRPM < 20) {
|
|
reversing = true;
|
|
} else {
|
|
reversing = false;
|
|
}
|
|
|
|
//set the engine audio volume and pitch according to input and current RPM
|
|
if (otherCarParts.engineAudio != null && !vehicleDestroyed) {
|
|
if (!reversing) {
|
|
otherCarParts.engineAudio.volume = Mathf.Lerp (otherCarParts.engineAudio.volume, Mathf.Clamp (motorInput, 0.35f, 0.85f), Time.deltaTime * 5);
|
|
} else {
|
|
otherCarParts.engineAudio.volume = Mathf.Lerp (otherCarParts.engineAudio.volume, Mathf.Clamp (Mathf.Abs (motorInput), 0.35f, 0.85f), Time.deltaTime * 5);
|
|
}
|
|
|
|
otherCarParts.engineAudio.pitch = Mathf.Lerp (otherCarParts.engineAudio.pitch,
|
|
Mathf.Lerp (1, 2, (currentRPM - settings.minRPM / 1.5f) / (settings.maxRPM + settings.minRPM)), currentDeltaTime * 5);
|
|
}
|
|
|
|
//if the current speed is higher that the max speed, stop apply motor torque to the powered wheels
|
|
if (currentSpeed > vehicleControllerSettings.maxForwardSpeed ||
|
|
Mathf.Abs (currentRearRPM / 2) > settings.rearRPMLimitForMaxSpeed ||
|
|
usingGravityControl) {
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = 0;
|
|
}
|
|
}
|
|
} else if (!reversing) {
|
|
//else if the vehicle is moving in fowards direction, apply motor torque to every powered wheel using the gear animation curve
|
|
float speedMultiplier = 1;
|
|
|
|
if (settings.useCurves) {
|
|
speedMultiplier = gearsList [currentGear].engineTorqueCurve.Evaluate (currentSpeed);
|
|
}
|
|
|
|
float motorTorqueValue = settings.engineTorque * Mathf.Clamp (motorInput, 0, 1) * boostInput * speedMultiplier;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = motorTorqueValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//if the vehicle is moving backwards, apply motor torque to every powered wheel
|
|
if (reversing) {
|
|
//if the current speed is lower than the maxBackWardSpeed, apply motor torque
|
|
if (currentSpeed < settings.maxBackWardSpeed && Mathf.Abs (currentRearRPM / 2) < (settings.rearEngineTorque + 500)) {
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = settings.rearEngineTorque * motorInput;
|
|
}
|
|
}
|
|
}
|
|
//else, stop adding motor torque
|
|
else {
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
if (currentWheel.powered) {
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vehicleDestroyed) {
|
|
if (vehicleControllerSettings.autoBrakeIfVehicleDestroyed) {
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = 0;
|
|
currentWheelCollider.brakeTorque = settings.brake / 10;
|
|
}
|
|
}
|
|
} else {
|
|
//if the vehicle is not being driving
|
|
if (!driving && !externalBrakeActive && !autobrakeActive) {
|
|
//stop the motor torque and apply brake torque to every wheel
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.motorTorque = 0;
|
|
currentWheelCollider.brakeTorque = settings.brake / 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
//set the smoke skid particles in every wheel
|
|
wheelGroundHit = new WheelHit ();
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
currentWheel = wheelsList [i];
|
|
|
|
currentWheelCollider = currentWheel.wheelCollider;
|
|
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHit);
|
|
|
|
//set the skid marks under every wheel
|
|
currentWheel.wheelSlipAmountSideways = Mathf.Abs (wheelGroundHit.sidewaysSlip);
|
|
currentWheel.wheelSlipAmountForward = Mathf.Abs (wheelGroundHit.forwardSlip);
|
|
|
|
if (currentWheel.wheelSlipAmountSideways > 0.25f || currentWheel.wheelSlipAmountForward > 0.5f) {
|
|
Vector3 skidPoint = wheelGroundHit.point + (2 * currentDeltaTime) * mainRigidbody.linearVelocity;
|
|
|
|
if (mainRigidbody.linearVelocity.magnitude > 1) {
|
|
currentWheel.lastSkidmark = skidMarksManager.AddSkidMark (skidPoint, wheelGroundHit.normal,
|
|
(currentWheel.wheelSlipAmountSideways / 2) + (currentWheel.wheelSlipAmountForward / 2.5f), currentWheel.lastSkidmark);
|
|
} else {
|
|
currentWheel.lastSkidmark = -1;
|
|
}
|
|
} else {
|
|
currentWheel.lastSkidmark = -1;
|
|
}
|
|
|
|
if (currentWheel.hasParticles) {
|
|
currentWheelCollider.GetGroundHit (out wheelGroundHit);
|
|
|
|
if (Mathf.Abs (wheelGroundHit.sidewaysSlip) > 0.25f || Mathf.Abs (wheelGroundHit.forwardSlip) > 0.5f) {
|
|
if (!currentWheel.wheelParticleSystem.isPlaying) {
|
|
currentWheel.wheelParticleSystem.Play ();
|
|
}
|
|
} else {
|
|
if (currentWheel.wheelParticleSystem.isPlaying) {
|
|
currentWheel.wheelParticleSystem.Stop ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//set the exhaust particles state
|
|
for (i = 0; i < otherCarParts.normalExhaust.Count; i++) {
|
|
currentParticleSystem = otherCarParts.normalExhaust [i];
|
|
|
|
if (isTurnedOn) {
|
|
if (currentSpeed < 10) {
|
|
if (!currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Play ();
|
|
}
|
|
} else {
|
|
if (currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Stop ();
|
|
}
|
|
}
|
|
} else {
|
|
if (currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Stop ();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < otherCarParts.heavyExhaust.Count; i++) {
|
|
|
|
currentParticleSystem = otherCarParts.heavyExhaust [i];
|
|
|
|
if (isTurnedOn) {
|
|
if (currentSpeed > 10 && motorInput > 0.1f) {
|
|
if (!currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Play ();
|
|
}
|
|
} else {
|
|
if (currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Stop ();
|
|
}
|
|
}
|
|
} else {
|
|
if (currentParticleSystem.isPlaying) {
|
|
currentParticleSystem.Stop ();
|
|
}
|
|
}
|
|
}
|
|
|
|
//check if the car is in the ground or not
|
|
anyOnGround = true;
|
|
int totalWheelsOnAir = 0;
|
|
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
if (!wheelsList [i].wheelCollider.isGrounded) {
|
|
//if the current wheel is in the air, increase the number of wheels in the air
|
|
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 == wheelsListCount && anyOnGround) {
|
|
anyOnGround = false;
|
|
}
|
|
|
|
if (interfaceInfo != null) {
|
|
if (interfaceActive != isTurnedOn) {
|
|
interfaceActive = isTurnedOn;
|
|
|
|
interfaceInfo.shipEnginesState (interfaceActive);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override bool isVehicleOnGround ()
|
|
{
|
|
return anyOnGround;
|
|
}
|
|
|
|
public override bool isDrivingActive ()
|
|
{
|
|
return driving;
|
|
}
|
|
|
|
public override void setEngineOnOrOffState ()
|
|
{
|
|
base.setEngineOnOrOffState ();
|
|
|
|
|
|
}
|
|
|
|
public override void pressHorn ()
|
|
{
|
|
base.pressHorn ();
|
|
|
|
setAudioState (otherCarParts.hornAudioElement, 5, 1, false, true, false);
|
|
}
|
|
|
|
public override void passengerGettingOnOff ()
|
|
{
|
|
vehicleBounceMovement (settings.horizontalLeanPassengerAmount, settings.verticalLeanPassengerAmount);
|
|
}
|
|
|
|
public void vehicleBounceMovement (float horizontalLeanAmount, float verticalLeanAmount)
|
|
{
|
|
if (!bounceVehicleOnPassengerGettingOnOff) {
|
|
return;
|
|
}
|
|
|
|
if (bounceCoroutine != null) {
|
|
StopCoroutine (bounceCoroutine);
|
|
}
|
|
|
|
bounceCoroutine = StartCoroutine (vehicleBounceMovementCoroutine (horizontalLeanAmount, verticalLeanAmount));
|
|
}
|
|
|
|
IEnumerator vehicleBounceMovementCoroutine (float horizontalLeanAmount, float verticalLeanAmount)
|
|
{
|
|
bouncingVehicle = true;
|
|
|
|
horizontalLean = Mathf.Clamp (horizontalLeanAmount, -settings.chassisLeanLimit, settings.chassisLeanLimit);
|
|
verticalLean = Mathf.Clamp (verticalLeanAmount, -settings.chassisLeanLimit, settings.chassisLeanLimit);
|
|
|
|
Quaternion chassisRotation = Quaternion.Euler (otherCarParts.chassis.transform.localRotation.x + verticalLean,
|
|
otherCarParts.chassis.transform.localRotation.y,
|
|
otherCarParts.chassis.transform.localRotation.z + horizontalLean);
|
|
|
|
Vector3 targetRotation = chassisRotation.eulerAngles;
|
|
Vector3 originalEuler = otherCarParts.chassis.transform.eulerAngles;
|
|
|
|
float t = 0;
|
|
|
|
while (t < 1 && otherCarParts.chassis.transform.localEulerAngles != targetRotation) {
|
|
t += Time.deltaTime * settings.leanPassengerSpeed;
|
|
|
|
otherCarParts.chassis.transform.localRotation = Quaternion.Slerp (otherCarParts.chassis.transform.localRotation, Quaternion.Euler (targetRotation), t);
|
|
}
|
|
|
|
bouncingVehicle = false;
|
|
|
|
yield return null;
|
|
}
|
|
|
|
//if the vehicle is using the gravity control, set the state in this component
|
|
public override void changeGravityControlUse (bool state)
|
|
{
|
|
base.changeGravityControlUse (state);
|
|
|
|
if (usingGravityControl) {
|
|
StartCoroutine (changeGear (0));
|
|
}
|
|
}
|
|
|
|
//the player is getting on or off from the vehicle, so
|
|
public override void changeVehicleState ()
|
|
{
|
|
base.changeVehicleState ();
|
|
|
|
if (interfaceInfo != null) {
|
|
interfaceInfo.enableOrDisableInterface (driving);
|
|
}
|
|
}
|
|
|
|
public override void setTurnOnState ()
|
|
{
|
|
setAudioState (otherCarParts.engineAudioElement, 5, 0, true, true, false);
|
|
setAudioState (otherCarParts.skidAudioElement, 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 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.skidAudioElement, 5, 0, false, false, false);
|
|
setAudioState (otherCarParts.engineStartAudioElement, 5, 0.7f, false, false, false);
|
|
|
|
skidMarksManager.setSkidsEnabledState (false);
|
|
|
|
vehicleDestroyed = true;
|
|
|
|
setTurnOffState (false);
|
|
|
|
//disable the skid particles
|
|
for (i = 0; i < wheelsListCount; i++) {
|
|
if (wheelsList [i].hasParticles) {
|
|
wheelsList [i].wheelParticleSystem.Stop ();
|
|
}
|
|
}
|
|
|
|
//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;
|
|
|
|
if (interfaceInfo != null) {
|
|
interfaceInfo.enableOrDisableInterface (false);
|
|
}
|
|
}
|
|
|
|
Coroutine rotatingVehicleCoroutine;
|
|
|
|
public void rotateVehicle ()
|
|
{
|
|
if (rotatingVehicleCoroutine != null) {
|
|
StopCoroutine (rotatingVehicleCoroutine);
|
|
}
|
|
|
|
rotatingVehicleCoroutine = StartCoroutine (rotateVehicleCoroutine ());
|
|
}
|
|
|
|
//reset the vehicle rotation if it is upside down
|
|
IEnumerator rotateVehicleCoroutine ()
|
|
{
|
|
rotating = true;
|
|
|
|
timeToStabilize = 0;
|
|
currentTimeStabilizing = 0;
|
|
|
|
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 * rotateVehicleUpwardSpeed;
|
|
|
|
transform.rotation = Quaternion.Slerp (currentRotation, dstRotPlayer, t);
|
|
|
|
mainRigidbody.linearVelocity = vector3Zero;
|
|
|
|
yield return null;
|
|
}
|
|
|
|
rotating = false;
|
|
}
|
|
|
|
//change the gear in the vehicle
|
|
IEnumerator changeGear (int gear)
|
|
{
|
|
changingGear = true;
|
|
|
|
setAudioState (gearsList [gear].gearShiftingAudioElement, 5, 0.3f, false, true, false);
|
|
|
|
WaitForSeconds delay = new WaitForSeconds (gearsList [gear].changeGearDuration);
|
|
|
|
yield return delay;
|
|
|
|
changingGear = false;
|
|
|
|
currentGear = gear;
|
|
|
|
currentGear = Mathf.Clamp (currentGear, 0, gearListCount - 1);
|
|
}
|
|
|
|
//if the vehicle is colliding, then
|
|
void OnCollisionStay (Collision collision)
|
|
{
|
|
//set the values to avoid stabilize the vehicle yet
|
|
mainRigidbody.freezeRotation = false;
|
|
|
|
colliding = true;
|
|
|
|
timeToStabilize = 0;
|
|
|
|
currentTimeStabilizing = 0;
|
|
}
|
|
|
|
//the vehicle is not colliding
|
|
void OnCollisionExit (Collision collision)
|
|
{
|
|
colliding = false;
|
|
}
|
|
|
|
//if the vehicle is using the boost, set the boost particles
|
|
public override void usingBoosting ()
|
|
{
|
|
base.usingBoosting ();
|
|
|
|
if (otherCarParts.boostParticles) {
|
|
for (int i = 0; i < boostingParticles.Count; i++) {
|
|
currentParticleSystem = boostingParticles [i];
|
|
|
|
if (usingBoost) {
|
|
if (!currentParticleSystem.isPlaying) {
|
|
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)
|
|
{
|
|
mainRigidbody.AddForce (mainRigidbody.mass * direction, ForceMode.Impulse);
|
|
}
|
|
|
|
public void useJumpPlatformParable (Vector3 direction)
|
|
{
|
|
Vector3 jumpForce = direction;
|
|
|
|
mainRigidbody.AddForce (jumpForce, ForceMode.VelocityChange);
|
|
}
|
|
|
|
public void setJumpPower (float newJumpPower)
|
|
{
|
|
vehicleControllerSettings.jumpPower = newJumpPower;
|
|
}
|
|
|
|
public void setNewJumpPower (float newJumpPower)
|
|
{
|
|
vehicleControllerSettings.jumpPower = newJumpPower * 100;
|
|
}
|
|
|
|
public void setOriginalJumpPower ()
|
|
{
|
|
vehicleControllerSettings.jumpPower = originalJumpPower;
|
|
}
|
|
|
|
public void setMaxSpeed (float maxSpeedValue)
|
|
{
|
|
vehicleControllerSettings.maxForwardSpeed = maxSpeedValue;
|
|
}
|
|
|
|
public void setMaxAcceleration (float maxAccelerationValue)
|
|
{
|
|
settings.engineTorque = maxAccelerationValue;
|
|
}
|
|
|
|
public void setMaxBrakePower (float maxBrakePower)
|
|
{
|
|
settings.brake = maxBrakePower;
|
|
}
|
|
|
|
public void setMaxTurboPower (float maxTurboPower)
|
|
{
|
|
vehicleControllerSettings.maxBoostMultiplier = maxTurboPower;
|
|
}
|
|
|
|
public void setCanJumpState (bool state)
|
|
{
|
|
vehicleControllerSettings.canJump = state;
|
|
}
|
|
|
|
public void setRotateVehicleUpwardState (bool state)
|
|
{
|
|
rotateVehicleUpward = state;
|
|
}
|
|
|
|
public void setPreserveDirectionWhileInAirState (bool state)
|
|
{
|
|
settings.preserveDirectionWhileInAir = state;
|
|
}
|
|
|
|
public void setPauseAutoRotationActiveState (bool state)
|
|
{
|
|
pauseAutoRotationActiveState = 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
//reset the collision values
|
|
mainRigidbody.freezeRotation = false;
|
|
|
|
colliding = true;
|
|
|
|
timeToStabilize = 0;
|
|
|
|
currentTimeStabilizing = 0;
|
|
}
|
|
|
|
public override void startBrakeVehicleToStopCompletely ()
|
|
{
|
|
braking = true;
|
|
|
|
externalBrakeActive = braking;
|
|
}
|
|
|
|
public override void endBrakeVehicleToStopCompletely ()
|
|
{
|
|
braking = false;
|
|
|
|
externalBrakeActive = braking;
|
|
}
|
|
|
|
public override void activateAutoBrakeOnGetOff ()
|
|
{
|
|
base.activateAutoBrakeOnGetOff ();
|
|
}
|
|
|
|
public override float getCurrentSpeed ()
|
|
{
|
|
return currentSpeed;
|
|
}
|
|
|
|
//CALL INPUT FUNCTIONS
|
|
public override void inputJump ()
|
|
{
|
|
if (driving && !usingGravityControl && isTurnedOn) {
|
|
//jump input
|
|
if (vehicleControllerSettings.canJump) {
|
|
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;
|
|
}
|
|
|
|
jumpInputPressed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void inputHoldOrReleaseJump (bool holdingButton)
|
|
{
|
|
if (driving && !usingGravityControl && isTurnedOn) {
|
|
if (vehicleControllerSettings.canImpulseHoldingJump && !usingHoverBoardWaypoint) {
|
|
if (holdingButton) {
|
|
if (Time.time > lastTimeJump + 0.2f) {
|
|
usingImpulse = true;
|
|
}
|
|
} else {
|
|
usingImpulse = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void inputHoldOrReleaseTurbo (bool holdingButton)
|
|
{
|
|
if (driving && !usingGravityControl && isTurnedOn && !usingHoverBoardWaypoint) {
|
|
if (holdingButton) {
|
|
//boost input
|
|
if (vehicleControllerSettings.canUseBoost) {
|
|
usingBoost = true;
|
|
|
|
//set the camera move away action
|
|
mainVehicleCameraController.usingBoost (true, vehicleControllerSettings.boostCameraShakeStateName,
|
|
vehicleControllerSettings.useBoostCameraShake, vehicleControllerSettings.moveCameraAwayOnBoost);
|
|
}
|
|
} else {
|
|
//stop boost input
|
|
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 && !usingGravityControl) {
|
|
pressHorn ();
|
|
}
|
|
}
|
|
|
|
public override void inputHoldOrReleaseBrake (bool holdingButton)
|
|
{
|
|
if (driving && !usingGravityControl) {
|
|
braking = holdingButton;
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class Gears
|
|
{
|
|
public string Name;
|
|
|
|
public float gearSpeed;
|
|
|
|
public float changeGearDuration = 0.5f;
|
|
|
|
[Space]
|
|
public AnimationCurve engineTorqueCurve;
|
|
|
|
public AudioClip gearShiftingClip;
|
|
public AudioElement gearShiftingAudioElement;
|
|
|
|
public void InitializeAudioElements ()
|
|
{
|
|
if (gearShiftingClip != null) {
|
|
gearShiftingAudioElement.clip = gearShiftingClip;
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class Wheels
|
|
{
|
|
public string Name;
|
|
public WheelCollider wheelCollider;
|
|
public GameObject wheelMesh;
|
|
public GameObject mudGuard;
|
|
public GameObject suspension;
|
|
public bool steerable;
|
|
public bool powered;
|
|
public bool leftSide;
|
|
public bool rightSide;
|
|
public ParticleSystem wheelParticleSystem;
|
|
|
|
public bool reverseSteer;
|
|
|
|
[HideInInspector] public bool hasMudGuard;
|
|
[HideInInspector] public bool hasSuspension;
|
|
[HideInInspector] public bool hasParticles;
|
|
|
|
[HideInInspector] public float lastWheelColliderRotationValue;
|
|
|
|
[HideInInspector] public Vector3 mudGuardOriginalLocalEuler;
|
|
[HideInInspector] public Vector3 mudGuardOffset;
|
|
[HideInInspector] public Vector3 suspensionOffset;
|
|
[HideInInspector] public float suspensionSpringPos;
|
|
[HideInInspector] public float rotationValue;
|
|
[HideInInspector] public float wheelSlipAmountSideways;
|
|
[HideInInspector] public float wheelSlipAmountForward;
|
|
[HideInInspector] public int lastSkidmark = -1;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OtherCarParts
|
|
{
|
|
public Transform SteeringWheel;
|
|
public Transform COM;
|
|
public GameObject wheelSlipPrefab;
|
|
public GameObject chassis;
|
|
public AudioClip engineStartClip;
|
|
public AudioElement engineStartAudioElement;
|
|
public AudioClip engineClip;
|
|
public AudioElement engineAudioElement;
|
|
public AudioClip engineEndClip;
|
|
public AudioElement engineEndAudioElement;
|
|
public AudioClip skidClip;
|
|
public AudioElement skidAudioElement;
|
|
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 skidAudio;
|
|
public AudioSource crashAudio;
|
|
public AudioSource gearShiftingSound;
|
|
public AudioSource hornAudio;
|
|
public GameObject boostParticles;
|
|
|
|
public void InitializeAudioElements ()
|
|
{
|
|
if (engineStartClip != null) {
|
|
engineStartAudioElement.clip = engineStartClip;
|
|
}
|
|
|
|
if (engineClip != null) {
|
|
engineAudioElement.clip = engineClip;
|
|
}
|
|
|
|
if (engineEndClip != null) {
|
|
engineEndAudioElement.clip = engineEndClip;
|
|
}
|
|
|
|
if (skidClip != null) {
|
|
skidAudioElement.clip = skidClip;
|
|
}
|
|
|
|
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 (skidAudio != null) {
|
|
skidAudioElement.audioSource = skidAudio;
|
|
}
|
|
|
|
foreach (var audioElement in crashAudioElements) {
|
|
if (crashAudio != null) {
|
|
audioElement.audioSource = crashAudio;
|
|
}
|
|
}
|
|
|
|
if (hornAudio != null) {
|
|
hornAudioElement.audioSource = hornAudio;
|
|
}
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class carSettings
|
|
{
|
|
public float engineTorque = 2500;
|
|
public float rearEngineTorque = 2500;
|
|
public float maxRPM = 6000;
|
|
public float minRPM = 1000;
|
|
public float steerAngleLimit;
|
|
public float highSpeedSteerAngle = 10;
|
|
public float highSpeedSteerAngleAtSpeed = 100;
|
|
public Vector2 driftAngleLimit = new Vector2 (-35, 35);
|
|
public float steerWheelRotationPercentage = 8000;
|
|
public int steeringAssistanceDivider = 5;
|
|
|
|
[Space]
|
|
|
|
public float rearRPMLimitForMaxSpeed = 3000;
|
|
|
|
[Space]
|
|
|
|
public float steerInputSpeed = 10;
|
|
|
|
public float brake = 4000;
|
|
public float maxBackWardSpeed;
|
|
|
|
public float antiRoll = 10000;
|
|
|
|
public bool useBrakeValueOnSteerableWheels;
|
|
public float brakeValueOnSteerableWheels;
|
|
|
|
[Space]
|
|
[Space]
|
|
[Space]
|
|
|
|
public Vector2 chassisLean;
|
|
public float chassisLeanLimit;
|
|
|
|
[Space]
|
|
[Space]
|
|
[Space]
|
|
|
|
public LayerMask layer;
|
|
|
|
public float gearShiftRate = 10;
|
|
public bool preserveDirectionWhileInAir;
|
|
|
|
public float minTimeToPreserveDirectionWhileInAir = 0.6f;
|
|
|
|
public bool useMaxTimeToPreserveDirectionWhileOnAir;
|
|
|
|
public float maxTimeToPreserveDirectionWhileOnAir;
|
|
|
|
public bool useCurves;
|
|
|
|
[Space]
|
|
[Space]
|
|
[Space]
|
|
|
|
public float horizontalLeanPassengerAmount;
|
|
public float verticalLeanPassengerAmount;
|
|
public float leanPassengerSpeed;
|
|
}
|
|
} |