Advertisement
Purianite

Untitled

Feb 20th, 2017
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.16 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using UnityEngine.SceneManagement; //TEMPORARY, REMOVE LATER
  4. using UnityEngine.UI;
  5.  
  6. public class CarController : MonoBehaviour {
  7.  
  8. public float deviceAccelerometerSensitivity = 2f; //how sensitive our mobile accelerometer will be
  9. public float deadZone = .001f; //controls mobile device tilting dead zone
  10. public float horizontal; //horizontal input control, either mobile control or keyboard
  11. public float maxSpeedToTurn = 0.25f; //keeps car from turning until it's reached this value
  12.  
  13. // the physical transforms for the car's wheels
  14. public Transform frontLeftWheel;
  15. public Transform frontRightWheel;
  16. public Transform rearLeftWheel;
  17. public Transform rearRightWheel;
  18.  
  19. //these transform parents will allow wheels to turn for steering/separates steering turn from acceleration turning
  20. public Transform LFWheelTransform;
  21. public Transform RFWheelTransform;
  22.  
  23. //do not adjust this, but you will be able to read it in the inspector, and read it's value for a speedometer
  24. public float mySpeed;
  25.  
  26. // car physics adjustments
  27. public float power = 1200f;  
  28. public float maxSpeed = 50f;
  29. public float carGrip = 70f;
  30. public float turnSpeed = 2.5f; //keep this value somewhere between 2.5 and 6.0
  31. public float driftPower = 1500f; //Higher power when drifting
  32. public float driftThreshold = 2.5f; //minimum slipSpeed to enter drift when tapping brake
  33. public float driftExitThreshold = 1.5f; //slipSpeed that has to be maintained to exit a drift
  34. public float driftExitTime = 0.75f; //time to maintain driftExitThreshold to exit drift
  35. public float driftIdleTime = 1.00f; //time to exit drift by gas with no steering
  36. public float driftMinSpeed = 20f; //minimum speed required to enter drift
  37. public float driftGrip = 40f; //grip value to change to in drift
  38. public float driftTurnSpeed = 1.8f; //Increased turn speed while drifting
  39. public float driftAngDrag = 0.5f; //Angular drag while drifting
  40. public float driftPowerMinSlide = 8f; //Minimum slideSpeed to have driftPower in effect
  41. public float criticalDriftGrip = 20f; //Lower grip when we're going REALLY sideways.
  42. public float criticalSlide = 0.5f; //slideSpeed considered critical, lower grip even further
  43. private float stateTimer = 0f; //state timer to count driftExitTime and whatever else
  44.  
  45. //bunch of variables we do not adjust, script handles these internally
  46. private float slideSpeed;
  47. private float baseCarGrip;
  48. private float baseTurnSpeed;
  49. private float basePower;
  50. private float baseAngDrag;
  51. private Vector3 carRight;
  52. private Vector3 carFwd;
  53. private Vector3 tempVEC;
  54. private Vector3 rotationAmount;
  55. private Vector3 accel;
  56. private float throttle;
  57. private Vector3 myRight;
  58. private Vector3 velo;
  59. private Vector3 flatVelo;
  60. private Vector3 relativeVelocity;
  61. private Vector3 dir;
  62. private Vector3 flatDir;
  63. private Vector3 carUp;
  64. private Transform carTransform;
  65. private Rigidbody thisRigidbody;
  66. private Vector3 engineForce;
  67. private float actualGrip;
  68. private Vector3 turnVec;
  69. private Vector3 imp;
  70. private float rev;
  71. private float actualTurn;
  72. private float carMass;
  73. private Transform[] wheelTransform = new Transform[4]; //these are the transforms for our 4 wheels
  74. private AudioSource myAudioSource;
  75. private bool onGround;
  76. private RaycastHit groundHit;
  77.  
  78. //Mobile control specific
  79. public float driftDeadZone = 0.2f;
  80.  
  81. //UI stuff
  82. public Text speedometer;
  83.  
  84.     enum CarStates
  85.     {
  86.         Normal,
  87.         Drift,
  88.         Idle
  89.     }
  90.  
  91.     CarStates carState = CarStates.Normal;
  92.  
  93.     void Start()
  94.     {
  95.         InitializeCar();
  96.     }
  97.  
  98.     void InitializeCar()  
  99.     {
  100.         //Get the base car grip and turn speed so we can reassign it upon exiting drift
  101.         baseCarGrip = carGrip;
  102.         baseTurnSpeed = turnSpeed;
  103.         basePower = power;
  104.         // Cache a reference to our car's transform
  105.         carTransform = GetComponent<Transform>();
  106.         // cache the rigidbody for our car
  107.         thisRigidbody = GetComponent<Rigidbody>();
  108.         baseAngDrag = thisRigidbody.angularDrag;
  109.         // cache a reference to the AudioSource
  110.         myAudioSource = GetComponent<AudioSource>();
  111.         // cache our vector up direction
  112.         carUp = carTransform.up;
  113.         // cache the mass of our vehicle
  114.         carMass = thisRigidbody.mass;
  115.         // cache the Forward World Vector for our car
  116.         carFwd = Vector3.forward;
  117.         // cache the World Right Vector for our car
  118.         carRight = Vector3.right;
  119.         // call to set up our wheels array
  120.         SetUpWheels();
  121.         // we set a COG here and lower the center of mass to a
  122.         //negative value in Y axis to prevent car from flipping over
  123.         thisRigidbody.centerOfMass = new Vector3(0f, -0.75f, .35f);  
  124.     }
  125.  
  126.     void Update()
  127.     {
  128.         // call the function to start processing all vehicle physics
  129.         CarPhysicsUpdate();
  130.  
  131.         //call the function to see what input we are using and apply it
  132.         CheckInput();
  133.  
  134.         /*if (Physics.Raycast(transform.position, -transform.up, out groundHit))
  135.         {
  136.             onGround = true;
  137.         }
  138.         else onGround = false;*/
  139.  
  140.         if (Input.GetKey(KeyCode.R))
  141.         {
  142.             SceneManager.LoadScene("TestTrack");
  143.         }
  144.  
  145.         //Update the UI
  146.         UIUpdate();
  147.     }
  148.  
  149.     void LateUpdate()
  150.     {
  151.         // this function makes the visual 3d wheels rotate and turn
  152.         RotateVisualWheels();
  153.  
  154.         //this is where we send to a function to do engine sounds
  155.         EngineSound();        
  156.     }
  157.  
  158.     void SetUpWheels()
  159.     {
  160.         if ((null == frontLeftWheel || null == frontRightWheel || null == rearLeftWheel || null == rearRightWheel))
  161.         {
  162.             Debug.LogError("One or more of the wheel transforms have not been assigned on the car");
  163.             Debug.Break();
  164.         }
  165.         else
  166.         {
  167.             //set up the car's wheel transforms
  168.             wheelTransform[0] = frontLeftWheel;
  169.             wheelTransform[1] = rearLeftWheel;
  170.             wheelTransform[2] = frontRightWheel;
  171.             wheelTransform[3] = rearRightWheel;
  172.         }
  173.     }
  174.  
  175.     void RotateVisualWheels()
  176.     {
  177.         Vector3 tmpEulerAngles = LFWheelTransform.localEulerAngles;  
  178.         tmpEulerAngles.y = horizontal * 30f;
  179.  
  180.         // front wheels visual rotation while steering the car
  181.         LFWheelTransform.localEulerAngles = tmpEulerAngles;
  182.         RFWheelTransform.localEulerAngles = tmpEulerAngles;
  183.  
  184.         rotationAmount = carRight * (relativeVelocity.z * 1.6f * Time.deltaTime * Mathf.Rad2Deg);
  185.  
  186.         wheelTransform[0].Rotate(rotationAmount);
  187.         wheelTransform[1].Rotate(rotationAmount);
  188.         wheelTransform[2].Rotate(rotationAmount);
  189.         wheelTransform[3].Rotate(rotationAmount);
  190.     }
  191.  
  192.     void CheckInput()
  193.     {
  194.         //Mobile platform turning input...testing to see if we are on a mobile device.              
  195.         if (Application.platform == RuntimePlatform.IPhonePlayer || (Application.platform == RuntimePlatform.Android))
  196.         {
  197.             // we give the acceleration a little boost to make turning more sensitive
  198.             accel = Input.acceleration * deviceAccelerometerSensitivity;
  199.  
  200.             if (accel.x > deadZone || accel.x < -deadZone)
  201.             {
  202.                 horizontal = accel.x;
  203.                 //Make minimum intensity when things are too low, might make tilt more responsive
  204.                 if (Mathf.Abs(horizontal) > driftDeadZone && Mathf.Abs(horizontal) < 0.5)
  205.                 {
  206.                     horizontal = Mathf.Sign(horizontal) / 2;
  207.                 }
  208.                 if (Mathf.Abs(horizontal) > 1)
  209.                 {
  210.                     horizontal = Mathf.Sign(horizontal);
  211.                 }
  212.             }
  213.             else
  214.             {
  215.                 horizontal = 0;
  216.             }
  217.             throttle = 0;
  218.  
  219.             foreach (Touch touch in Input.touches)
  220.             {
  221.                 if (touch.position.x > Screen.width - Screen.width / 3 && touch.position.y < Screen.height / 3)
  222.                 {
  223.                     throttle = 1f;
  224.                 }
  225.                 else if (touch.position.x < Screen.width / 3 && touch.position.y < Screen.height / 3)
  226.                 {
  227.                     throttle = -1f;
  228.                 }
  229.             }
  230.         }
  231.         else //this input is for the Unity editor
  232.         {
  233.             //Use the Keyboard for all car input
  234.             horizontal = Input.GetAxis("Horizontal");
  235.             throttle = Input.GetAxis("Vertical");
  236.         }
  237.     }
  238.  
  239.     void CarPhysicsUpdate()
  240.     {
  241.         //grab all the physics info we need to calc everything
  242.         myRight = carTransform.right;
  243.  
  244.         // find our velocity
  245.         velo = thisRigidbody.velocity;
  246.  
  247.         tempVEC = new Vector3(velo.x, 0f, velo.z);
  248.  
  249.         // figure out our velocity without y movement - our flat velocity
  250.         flatVelo = tempVEC;
  251.  
  252.         // find out which direction we are moving in
  253.         dir = transform.TransformDirection(carFwd);
  254.  
  255.         tempVEC = new Vector3(dir.x, 0, dir.z);
  256.  
  257.         // calculate our direction, removing y movement - our flat direction
  258.         flatDir = Vector3.Normalize(tempVEC);
  259.  
  260.         // calculate relative velocity
  261.         relativeVelocity = carTransform.InverseTransformDirection(flatVelo);
  262.  
  263.         // calculate how much we are sliding (find out movement along our x axis)
  264.         slideSpeed = Vector3.Dot(myRight, flatVelo);
  265.         Debug.Log(slideSpeed);
  266.  
  267.         // calculate current speed (the magnitude of the flat velocity)
  268.         mySpeed = flatVelo.magnitude;
  269.  
  270.         // check to see if we are moving in reverse
  271.         rev = Mathf.Sign(Vector3.Dot(flatVelo, flatDir));
  272.  
  273.         // calculate engine force with our flat direction vector and acceleration
  274.         //engineForce = (flatDir * (power * throttle) * carMass);
  275.         engineForce = (flatDir * ((power * throttle) - (0.05f * Mathf.Pow(mySpeed, 2f) * carMass)));
  276.  
  277.         //Rewrite as switch case
  278.         if (carState == CarStates.Normal && throttle < 0)
  279.         {
  280.             if (mySpeed >= driftMinSpeed && Mathf.Abs(slideSpeed) >= driftThreshold)
  281.             {
  282.                 stateTimer = 0;
  283.                 carGrip = driftGrip;
  284.                 turnSpeed = driftTurnSpeed;
  285.                 //power = driftPower;
  286.                 thisRigidbody.angularDrag = driftAngDrag;
  287.                 //Debug.Log("Entered drift");
  288.                 carState = CarStates.Drift;
  289.             }
  290.         }
  291.  
  292.         if (carState == CarStates.Drift)
  293.         {
  294.             if (Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) >= driftPowerMinSlide)
  295.             {
  296.                 power = driftPower;
  297.             }
  298.             else power = basePower;
  299.  
  300.             //enter critical drift when we go really sideways
  301.             if (Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) >= criticalSlide)
  302.             {
  303.                 carGrip = criticalDriftGrip;
  304.             }
  305.  
  306.             //exit when we're not extremely sideways
  307.             if (carGrip == criticalDriftGrip && Mathf.Abs(slideSpeed)/Mathf.Abs(mySpeed) < criticalSlide)
  308.             {
  309.                 carGrip = driftGrip;
  310.             }
  311.         }
  312.  
  313.         if (carState == CarStates.Drift)
  314.         {
  315.             //Exit drift if slide speed is under threshold or gas with no steering for 0.4 seconds
  316.             if (Mathf.Abs(slideSpeed) <= driftExitThreshold || (throttle > 0 && Mathf.Abs(horizontal) < driftDeadZone))
  317.             {
  318.                 stateTimer += Time.deltaTime;
  319.             }
  320.             else stateTimer = 0;
  321.  
  322.             if (stateTimer >= driftExitTime && Mathf.Abs(slideSpeed) <= driftExitThreshold)
  323.             {
  324.                 stateTimer = 0;
  325.                 carGrip = baseCarGrip;
  326.                 turnSpeed = baseTurnSpeed;
  327.                 power = basePower;
  328.                 thisRigidbody.angularDrag = baseAngDrag;
  329.                 //Debug.Log("Exited drift");
  330.                 carState = CarStates.Normal;
  331.             }
  332.  
  333.             if (stateTimer >= driftIdleTime)
  334.             {
  335.                 stateTimer = 0;
  336.                 carGrip = baseCarGrip;
  337.                 turnSpeed = baseTurnSpeed;
  338.                 power = basePower;
  339.                 thisRigidbody.angularDrag = baseAngDrag;
  340.                 //Debug.Log("Exited drift");
  341.                 carState = CarStates.Normal;
  342.             }
  343.         }
  344.  
  345.         // do turning
  346.         actualTurn = horizontal;
  347.  
  348.         // if we're in reverse, we reverse the turning direction too
  349.         if (rev < 0.1f)
  350.         {
  351.             actualTurn = -actualTurn;
  352.         }
  353.  
  354.         // calculate torque for applying to our rigidbody
  355.         turnVec = (((carUp * turnSpeed) * actualTurn) * carMass) * 800f;
  356.  
  357.         // calculate impulses to simulate grip by taking our right vector, reversing the slidespeed and
  358.         // multiplying that by our mass, to give us a completely 'corrected' force that would completely
  359.         // stop sliding. we then multiply that by our grip amount (which is, technically, a slide amount) which
  360.         // reduces the corrected force so that it only helps to reduce sliding rather than completely
  361.         // stop it
  362.  
  363.         actualGrip = Mathf.Lerp(100f, carGrip, mySpeed * 0.02f);
  364.         imp = myRight * (-slideSpeed * carMass * actualGrip);
  365.         //imp = myRight * ((8 * (-slideSpeed / mySpeed)) * carMass * actualGrip);
  366.  
  367.     }
  368.  
  369.     //this controls the sound of the engine audio by adjusting the pitch of our sound file
  370.     void EngineSound()
  371.     {
  372.         myAudioSource.pitch = 0.30f + mySpeed * 0.025f;
  373.  
  374.         if (mySpeed > 30f)
  375.         {
  376.             myAudioSource.pitch = 0.25f + mySpeed * 0.015f;
  377.         }
  378.         if (mySpeed > 40f)
  379.         {
  380.             myAudioSource.pitch = 0.20f + mySpeed * 0.013f;
  381.         }
  382.         if (mySpeed > 49f)
  383.         {
  384.             myAudioSource.pitch = 0.15f + mySpeed * 0.011f;
  385.         }
  386.         //ensures we dont exceed to crazy of a pitch by resetting it back to default 2
  387.         if (myAudioSource.pitch > 2.0f)
  388.         {
  389.             myAudioSource.pitch = 2.0f;
  390.         }
  391.     }
  392.  
  393.     void OnCollisionStay(Collision collisionInfo)
  394.     {
  395.         if (collisionInfo.gameObject.CompareTag("Environment"))
  396.         {
  397.             onGround = true;          
  398.         }
  399.     }
  400.  
  401.     void OnCollisionExit(Collision collisionInfo)
  402.     {
  403.         if (collisionInfo.gameObject.CompareTag("Environment"))
  404.         {
  405.             onGround = false;
  406.         }
  407.     }
  408.  
  409.     void FixedUpdate()
  410.     {
  411.         if (onGround)
  412.         {
  413.             if (mySpeed < maxSpeed)
  414.             {
  415.                 // apply the engine force to the rigidbody
  416.                 thisRigidbody.AddForce(engineForce * Time.deltaTime);
  417.             }
  418.             //if we're going to slow to allow car to rotate around
  419.             if (mySpeed > maxSpeedToTurn)
  420.             {
  421.                 // apply torque to our rigidbody
  422.                 thisRigidbody.AddTorque(turnVec * Time.deltaTime);
  423.             }
  424.             else if (mySpeed < maxSpeedToTurn)
  425.             {
  426.                 return;
  427.             }
  428.             // apply forces to our rigidbody for grip
  429.             thisRigidbody.AddForce(imp * Time.deltaTime);
  430.         }
  431.     }
  432.  
  433.     void UIUpdate()
  434.     {
  435.         speedometer.text = (Mathf.Round(mySpeed * 3.6f)).ToString() + " km/h";
  436.     }
  437. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement