Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using UnityEngine.SceneManagement; //TEMPORARY, REMOVE LATER
- using UnityEngine.UI;
- public class CarController : MonoBehaviour {
- public float deviceAccelerometerSensitivity = 2f; //how sensitive our mobile accelerometer will be
- public float deadZone = .001f; //controls mobile device tilting dead zone
- public float horizontal; //horizontal input control, either mobile control or keyboard
- public float maxSpeedToTurn = 0.25f; //keeps car from turning until it's reached this value
- // the physical transforms for the car's wheels
- public Transform frontLeftWheel;
- public Transform frontRightWheel;
- public Transform rearLeftWheel;
- public Transform rearRightWheel;
- //these transform parents will allow wheels to turn for steering/separates steering turn from acceleration turning
- public Transform LFWheelTransform;
- public Transform RFWheelTransform;
- //do not adjust this, but you will be able to read it in the inspector, and read it's value for a speedometer
- public float mySpeed;
- // car physics adjustments
- public float power = 1200f;
- public float maxSpeed = 50f;
- public float carGrip = 70f;
- public float turnSpeed = 2.5f; //keep this value somewhere between 2.5 and 6.0
- public float driftPower = 1500f; //Higher power when drifting
- public float driftThreshold = 2.5f; //minimum slipSpeed to enter drift when tapping brake
- public float driftExitThreshold = 1.5f; //slipSpeed that has to be maintained to exit a drift
- public float driftExitTime = 0.75f; //time to maintain driftExitThreshold to exit drift
- public float driftIdleTime = 1.00f; //time to exit drift by gas with no steering
- public float driftMinSpeed = 20f; //minimum speed required to enter drift
- public float driftGrip = 40f; //grip value to change to in drift
- public float driftTurnSpeed = 1.8f; //Increased turn speed while drifting
- public float driftAngDrag = 0.5f; //Angular drag while drifting
- public float driftPowerMinSlide = 8f; //Minimum slideSpeed to have driftPower in effect
- public float criticalDriftGrip = 20f; //Lower grip when we're going REALLY sideways.
- public float criticalSlide = 0.5f; //slideSpeed considered critical, lower grip even further
- private float stateTimer = 0f; //state timer to count driftExitTime and whatever else
- //bunch of variables we do not adjust, script handles these internally
- private float slideSpeed;
- private float baseCarGrip;
- private float baseTurnSpeed;
- private float basePower;
- private float baseAngDrag;
- private Vector3 carRight;
- private Vector3 carFwd;
- private Vector3 tempVEC;
- private Vector3 rotationAmount;
- private Vector3 accel;
- private float throttle;
- private Vector3 myRight;
- private Vector3 velo;
- private Vector3 flatVelo;
- private Vector3 relativeVelocity;
- private Vector3 dir;
- private Vector3 flatDir;
- private Vector3 carUp;
- private Transform carTransform;
- private Rigidbody thisRigidbody;
- private Vector3 engineForce;
- private float actualGrip;
- private Vector3 turnVec;
- private Vector3 imp;
- private float rev;
- private float actualTurn;
- private float carMass;
- private Transform[] wheelTransform = new Transform[4]; //these are the transforms for our 4 wheels
- private AudioSource myAudioSource;
- private bool onGround;
- private RaycastHit groundHit;
- //Mobile control specific
- public float driftDeadZone = 0.2f;
- //UI stuff
- public Text speedometer;
- enum CarStates
- {
- Normal,
- Drift,
- Idle
- }
- CarStates carState = CarStates.Normal;
- void Start()
- {
- InitializeCar();
- }
- void InitializeCar()
- {
- //Get the base car grip and turn speed so we can reassign it upon exiting drift
- baseCarGrip = carGrip;
- baseTurnSpeed = turnSpeed;
- basePower = power;
- // Cache a reference to our car's transform
- carTransform = GetComponent<Transform>();
- // cache the rigidbody for our car
- thisRigidbody = GetComponent<Rigidbody>();
- baseAngDrag = thisRigidbody.angularDrag;
- // cache a reference to the AudioSource
- myAudioSource = GetComponent<AudioSource>();
- // cache our vector up direction
- carUp = carTransform.up;
- // cache the mass of our vehicle
- carMass = thisRigidbody.mass;
- // cache the Forward World Vector for our car
- carFwd = Vector3.forward;
- // cache the World Right Vector for our car
- carRight = Vector3.right;
- // call to set up our wheels array
- SetUpWheels();
- // we set a COG here and lower the center of mass to a
- //negative value in Y axis to prevent car from flipping over
- thisRigidbody.centerOfMass = new Vector3(0f, -0.75f, .35f);
- }
- void Update()
- {
- // call the function to start processing all vehicle physics
- CarPhysicsUpdate();
- //call the function to see what input we are using and apply it
- CheckInput();
- /*if (Physics.Raycast(transform.position, -transform.up, out groundHit))
- {
- onGround = true;
- }
- else onGround = false;*/
- if (Input.GetKey(KeyCode.R))
- {
- SceneManager.LoadScene("TestTrack");
- }
- //Update the UI
- UIUpdate();
- }
- void LateUpdate()
- {
- // this function makes the visual 3d wheels rotate and turn
- RotateVisualWheels();
- //this is where we send to a function to do engine sounds
- EngineSound();
- }
- void SetUpWheels()
- {
- if ((null == frontLeftWheel || null == frontRightWheel || null == rearLeftWheel || null == rearRightWheel))
- {
- Debug.LogError("One or more of the wheel transforms have not been assigned on the car");
- Debug.Break();
- }
- else
- {
- //set up the car's wheel transforms
- wheelTransform[0] = frontLeftWheel;
- wheelTransform[1] = rearLeftWheel;
- wheelTransform[2] = frontRightWheel;
- wheelTransform[3] = rearRightWheel;
- }
- }
- void RotateVisualWheels()
- {
- Vector3 tmpEulerAngles = LFWheelTransform.localEulerAngles;
- tmpEulerAngles.y = horizontal * 30f;
- // front wheels visual rotation while steering the car
- LFWheelTransform.localEulerAngles = tmpEulerAngles;
- RFWheelTransform.localEulerAngles = tmpEulerAngles;
- rotationAmount = carRight * (relativeVelocity.z * 1.6f * Time.deltaTime * Mathf.Rad2Deg);
- wheelTransform[0].Rotate(rotationAmount);
- wheelTransform[1].Rotate(rotationAmount);
- wheelTransform[2].Rotate(rotationAmount);
- wheelTransform[3].Rotate(rotationAmount);
- }
- void CheckInput()
- {
- //Mobile platform turning input...testing to see if we are on a mobile device.
- if (Application.platform == RuntimePlatform.IPhonePlayer || (Application.platform == RuntimePlatform.Android))
- {
- // we give the acceleration a little boost to make turning more sensitive
- accel = Input.acceleration * deviceAccelerometerSensitivity;
- if (accel.x > deadZone || accel.x < -deadZone)
- {
- horizontal = accel.x;
- //Make minimum intensity when things are too low, might make tilt more responsive
- if (Mathf.Abs(horizontal) > driftDeadZone && Mathf.Abs(horizontal) < 0.5)
- {
- horizontal = Mathf.Sign(horizontal) / 2;
- }
- if (Mathf.Abs(horizontal) > 1)
- {
- horizontal = Mathf.Sign(horizontal);
- }
- }
- else
- {
- horizontal = 0;
- }
- throttle = 0;
- foreach (Touch touch in Input.touches)
- {
- if (touch.position.x > Screen.width - Screen.width / 3 && touch.position.y < Screen.height / 3)
- {
- throttle = 1f;
- }
- else if (touch.position.x < Screen.width / 3 && touch.position.y < Screen.height / 3)
- {
- throttle = -1f;
- }
- }
- }
- else //this input is for the Unity editor
- {
- //Use the Keyboard for all car input
- horizontal = Input.GetAxis("Horizontal");
- throttle = Input.GetAxis("Vertical");
- }
- }
- void CarPhysicsUpdate()
- {
- //grab all the physics info we need to calc everything
- myRight = carTransform.right;
- // find our velocity
- velo = thisRigidbody.velocity;
- tempVEC = new Vector3(velo.x, 0f, velo.z);
- // figure out our velocity without y movement - our flat velocity
- flatVelo = tempVEC;
- // find out which direction we are moving in
- dir = transform.TransformDirection(carFwd);
- tempVEC = new Vector3(dir.x, 0, dir.z);
- // calculate our direction, removing y movement - our flat direction
- flatDir = Vector3.Normalize(tempVEC);
- // calculate relative velocity
- relativeVelocity = carTransform.InverseTransformDirection(flatVelo);
- // calculate how much we are sliding (find out movement along our x axis)
- slideSpeed = Vector3.Dot(myRight, flatVelo);
- Debug.Log(slideSpeed);
- // calculate current speed (the magnitude of the flat velocity)
- mySpeed = flatVelo.magnitude;
- // check to see if we are moving in reverse
- rev = Mathf.Sign(Vector3.Dot(flatVelo, flatDir));
- // calculate engine force with our flat direction vector and acceleration
- //engineForce = (flatDir * (power * throttle) * carMass);
- engineForce = (flatDir * ((power * throttle) - (0.05f * Mathf.Pow(mySpeed, 2f) * carMass)));
- //Rewrite as switch case
- if (carState == CarStates.Normal && throttle < 0)
- {
- if (mySpeed >= driftMinSpeed && Mathf.Abs(slideSpeed) >= driftThreshold)
- {
- stateTimer = 0;
- carGrip = driftGrip;
- turnSpeed = driftTurnSpeed;
- //power = driftPower;
- thisRigidbody.angularDrag = driftAngDrag;
- //Debug.Log("Entered drift");
- carState = CarStates.Drift;
- }
- }
- if (carState == CarStates.Drift)
- {
- if (Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) >= driftPowerMinSlide)
- {
- power = driftPower;
- }
- else power = basePower;
- //enter critical drift when we go really sideways
- if (Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) >= criticalSlide)
- {
- carGrip = criticalDriftGrip;
- }
- //exit when we're not extremely sideways
- if (carGrip == criticalDriftGrip && Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) < criticalSlide)
- {
- carGrip = driftGrip;
- }
- }
- if (carState == CarStates.Drift)
- {
- //Exit drift if slide speed is under threshold or gas with no steering for 0.4 seconds
- if (Mathf.Abs(slideSpeed) <= driftExitThreshold || (throttle > 0 && Mathf.Abs(horizontal) < driftDeadZone))
- {
- stateTimer += Time.deltaTime;
- }
- else stateTimer = 0;
- if (stateTimer >= driftExitTime && Mathf.Abs(slideSpeed) <= driftExitThreshold)
- {
- stateTimer = 0;
- carGrip = baseCarGrip;
- turnSpeed = baseTurnSpeed;
- power = basePower;
- thisRigidbody.angularDrag = baseAngDrag;
- //Debug.Log("Exited drift");
- carState = CarStates.Normal;
- }
- if (stateTimer >= driftIdleTime)
- {
- stateTimer = 0;
- carGrip = baseCarGrip;
- turnSpeed = baseTurnSpeed;
- power = basePower;
- thisRigidbody.angularDrag = baseAngDrag;
- //Debug.Log("Exited drift");
- carState = CarStates.Normal;
- }
- }
- // do turning
- actualTurn = horizontal;
- // if we're in reverse, we reverse the turning direction too
- if (rev < 0.1f)
- {
- actualTurn = -actualTurn;
- }
- // calculate torque for applying to our rigidbody
- turnVec = (((carUp * turnSpeed) * actualTurn) * carMass) * 800f;
- // calculate impulses to simulate grip by taking our right vector, reversing the slidespeed and
- // multiplying that by our mass, to give us a completely 'corrected' force that would completely
- // stop sliding. we then multiply that by our grip amount (which is, technically, a slide amount) which
- // reduces the corrected force so that it only helps to reduce sliding rather than completely
- // stop it
- actualGrip = Mathf.Lerp(100f, carGrip, mySpeed * 0.02f);
- imp = myRight * (-slideSpeed * carMass * actualGrip);
- //imp = myRight * ((8 * (-slideSpeed / mySpeed)) * carMass * actualGrip);
- }
- //this controls the sound of the engine audio by adjusting the pitch of our sound file
- void EngineSound()
- {
- myAudioSource.pitch = 0.30f + mySpeed * 0.025f;
- if (mySpeed > 30f)
- {
- myAudioSource.pitch = 0.25f + mySpeed * 0.015f;
- }
- if (mySpeed > 40f)
- {
- myAudioSource.pitch = 0.20f + mySpeed * 0.013f;
- }
- if (mySpeed > 49f)
- {
- myAudioSource.pitch = 0.15f + mySpeed * 0.011f;
- }
- //ensures we dont exceed to crazy of a pitch by resetting it back to default 2
- if (myAudioSource.pitch > 2.0f)
- {
- myAudioSource.pitch = 2.0f;
- }
- }
- void OnCollisionStay(Collision collisionInfo)
- {
- if (collisionInfo.gameObject.CompareTag("Environment"))
- {
- onGround = true;
- }
- }
- void OnCollisionExit(Collision collisionInfo)
- {
- if (collisionInfo.gameObject.CompareTag("Environment"))
- {
- onGround = false;
- }
- }
- void FixedUpdate()
- {
- if (onGround)
- {
- if (mySpeed < maxSpeed)
- {
- // apply the engine force to the rigidbody
- thisRigidbody.AddForce(engineForce * Time.deltaTime);
- }
- //if we're going to slow to allow car to rotate around
- if (mySpeed > maxSpeedToTurn)
- {
- // apply torque to our rigidbody
- thisRigidbody.AddTorque(turnVec * Time.deltaTime);
- }
- else if (mySpeed < maxSpeedToTurn)
- {
- return;
- }
- // apply forces to our rigidbody for grip
- thisRigidbody.AddForce(imp * Time.deltaTime);
- }
- }
- void UIUpdate()
- {
- speedometer.text = (Mathf.Round(mySpeed * 3.6f)).ToString() + " km/h";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement