Advertisement
Guest User

CarControlelr.cs

a guest
Sep 7th, 2019
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.10 KB | None | 0 0
  1. using System;
  2. using UnityEngine;
  3.  
  4. namespace UnityStandardAssets.Vehicles.Car
  5. {
  6.     internal enum CarDriveType
  7.     {
  8.         FrontWheelDrive,
  9.         RearWheelDrive,
  10.         FourWheelDrive
  11.     }
  12.  
  13.     internal enum SpeedType
  14.     {
  15.         MPH,
  16.         KPH
  17.     }
  18.  
  19.     public class CarController : MonoBehaviour
  20.     {
  21.         [SerializeField] private CarDriveType m_CarDriveType = CarDriveType.FourWheelDrive;
  22.         [SerializeField] private WheelCollider[] m_WheelColliders = new WheelCollider[4];
  23.         [SerializeField] private GameObject[] m_WheelMeshes = new GameObject[4];
  24.         [SerializeField] private WheelEffects[] m_WheelEffects = new WheelEffects[4];
  25.         [SerializeField] private Vector3 m_CentreOfMassOffset;
  26.         [SerializeField] private float m_MaximumSteerAngle;
  27.         [Range(0, 1)] [SerializeField] private float m_SteerHelper; // 0 is raw physics , 1 the car will grip in the direction it is facing
  28.         [Range(0, 1)] [SerializeField] private float m_TractionControl; // 0 is no traction control, 1 is full interference
  29.         [SerializeField] private float m_FullTorqueOverAllWheels;
  30.         [SerializeField] private float m_ReverseTorque;
  31.         [SerializeField] private float m_MaxHandbrakeTorque;
  32.         [SerializeField] private float m_Downforce = 100f;
  33.         [SerializeField] private SpeedType m_SpeedType;
  34.         [SerializeField] private float m_Topspeed = 200;
  35.         [SerializeField] private static int NoOfGears = 5;
  36.         [SerializeField] private float m_RevRangeBoundary = 1f;
  37.         [SerializeField] private float m_SlipLimit;
  38.         [SerializeField] private float m_BrakeTorque;
  39.  
  40.         private Quaternion[] m_WheelMeshLocalRotations;
  41.         private Vector3 m_Prevpos, m_Pos;
  42.         private float m_SteerAngle;
  43.         private int m_GearNum;
  44.         private float m_GearFactor;
  45.         private float m_OldRotation;
  46.         private float m_CurrentTorque;
  47.         private Rigidbody m_Rigidbody;
  48.         private const float k_ReversingThreshold = 0.01f;
  49.  
  50.         public bool Skidding { get; private set; }
  51.         public float BrakeInput { get; private set; }
  52.         public float CurrentSteerAngle{ get { return m_SteerAngle; }}
  53.         public float CurrentSpeed{ get { return m_Rigidbody.velocity.magnitude*2.23693629f; }}
  54.         public float MaxSpeed{get { return m_Topspeed; }}
  55.         public float Revs { get; private set; }
  56.         public float AccelInput { get; private set; }
  57.  
  58.         private void Update()
  59.         {
  60.             //print("Current Speed: " + CurrentSpeed + " M/S" + " AccelInput: " + AccelInput
  61.               //  + " Current Torque " + m_CurrentTorque);
  62.         }
  63.  
  64.         // Use this for initialization
  65.         private void Start()
  66.         {
  67.             m_WheelMeshLocalRotations = new Quaternion[4];
  68.             for (int i = 0; i < 4; i++)
  69.             {
  70.                 m_WheelMeshLocalRotations[i] = m_WheelMeshes[i].transform.localRotation;
  71.             }
  72.             m_WheelColliders[0].attachedRigidbody.centerOfMass = m_CentreOfMassOffset;
  73.  
  74.             m_MaxHandbrakeTorque = float.MaxValue;
  75.  
  76.             m_Rigidbody = GetComponent<Rigidbody>();
  77.             m_CurrentTorque = m_FullTorqueOverAllWheels - (m_TractionControl*m_FullTorqueOverAllWheels);
  78.         }
  79.  
  80.  
  81.         private void GearChanging()
  82.         {
  83.             float f = Mathf.Abs(CurrentSpeed/MaxSpeed);
  84.             float upgearlimit = (1/(float) NoOfGears)*(m_GearNum + 1);
  85.             float downgearlimit = (1/(float) NoOfGears)*m_GearNum;
  86.  
  87.             if (m_GearNum > 0 && f < downgearlimit)
  88.             {
  89.                 m_GearNum--;
  90.             }
  91.  
  92.             if (f > upgearlimit && (m_GearNum < (NoOfGears - 1)))
  93.             {
  94.                 m_GearNum++;
  95.             }
  96.         }
  97.  
  98.  
  99.         // simple function to add a curved bias towards 1 for a value in the 0-1 range
  100.         private static float CurveFactor(float factor)
  101.         {
  102.             return 1 - (1 - factor)*(1 - factor);
  103.         }
  104.  
  105.  
  106.         // unclamped version of Lerp, to allow value to exceed the from-to range
  107.         private static float ULerp(float from, float to, float value)
  108.         {
  109.             return (1.0f - value)*from + value*to;
  110.         }
  111.  
  112.  
  113.         private void CalculateGearFactor()
  114.         {
  115.             float f = (1/(float) NoOfGears);
  116.             // gear factor is a normalised representation of the current speed within the current gear's range of speeds.
  117.             // We smooth towards the 'target' gear factor, so that revs don't instantly snap up or down when changing gear.
  118.             var targetGearFactor = Mathf.InverseLerp(f*m_GearNum, f*(m_GearNum + 1), Mathf.Abs(CurrentSpeed/MaxSpeed));
  119.             m_GearFactor = Mathf.Lerp(m_GearFactor, targetGearFactor, Time.deltaTime*5f);
  120.         }
  121.  
  122.  
  123.         private void CalculateRevs()
  124.         {
  125.             // calculate engine revs (for display / sound)
  126.             // (this is done in retrospect - revs are not used in force/power calculations)
  127.             CalculateGearFactor();
  128.             var gearNumFactor = m_GearNum/(float) NoOfGears;
  129.             var revsRangeMin = ULerp(0f, m_RevRangeBoundary, CurveFactor(gearNumFactor));
  130.             var revsRangeMax = ULerp(m_RevRangeBoundary, 1f, gearNumFactor);
  131.             Revs = ULerp(revsRangeMin, revsRangeMax, m_GearFactor);
  132.         }
  133.  
  134.  
  135.         public void Move(float steering, float accel, float footbrake, float handbrake)
  136.         {
  137.             for (int i = 0; i < 4; i++)
  138.             {
  139.                 Quaternion quat;
  140.                 Vector3 position;
  141.                 m_WheelColliders[i].GetWorldPose(out position, out quat);
  142.                 m_WheelMeshes[i].transform.position = position;
  143.                 m_WheelMeshes[i].transform.rotation = quat;
  144.             }
  145.  
  146.             //clamp input values
  147.             steering = Mathf.Clamp(steering, -1, 1);
  148.             AccelInput = accel = Mathf.Clamp(accel, 0, 1);
  149.             BrakeInput = footbrake = -1 * Mathf.Clamp(footbrake, -1, 0);
  150.            
  151.             handbrake = Mathf.Clamp(handbrake, 0, 1);
  152.  
  153.             //Set the steer on the front wheels.
  154.             //Assuming that wheels 0 and 1 are the front wheels.
  155.             m_SteerAngle = steering*m_MaximumSteerAngle;
  156.             m_WheelColliders[0].steerAngle = m_SteerAngle;
  157.             m_WheelColliders[1].steerAngle = m_SteerAngle;
  158.  
  159.             SteerHelper();
  160.             ApplyDrive(accel, footbrake);
  161.             CapSpeed();
  162.  
  163.             //Set the handbrake.
  164.             //Assuming that wheels 2 and 3 are the rear wheels.
  165.             if (handbrake > 0f)
  166.             {
  167.                 var hbTorque = handbrake*m_MaxHandbrakeTorque;
  168.                 m_WheelColliders[2].brakeTorque = hbTorque;
  169.                 m_WheelColliders[3].brakeTorque = hbTorque;
  170.             }
  171.             else
  172.             {
  173.                 m_WheelColliders[2].brakeTorque = 0;
  174.                 m_WheelColliders[3].brakeTorque = 0;
  175.             }
  176.  
  177.  
  178.             CalculateRevs();
  179.             GearChanging();
  180.  
  181.             AddDownForce();
  182.             //CheckForWheelSpin();
  183.             TractionControl();
  184.         }
  185.  
  186.  
  187.         private void CapSpeed()
  188.         {
  189.             float speed = m_Rigidbody.velocity.magnitude;
  190.             switch (m_SpeedType)
  191.             {
  192.                 case SpeedType.MPH:
  193.  
  194.                     speed *= 2.23693629f;
  195.                     if (speed > m_Topspeed)
  196.                         m_Rigidbody.velocity = (m_Topspeed/2.23693629f) * m_Rigidbody.velocity.normalized;
  197.                     break;
  198.  
  199.                 case SpeedType.KPH:
  200.                     speed *= 3.6f;
  201.                     if (speed > m_Topspeed)
  202.                         m_Rigidbody.velocity = (m_Topspeed/3.6f) * m_Rigidbody.velocity.normalized;
  203.                     break;
  204.             }
  205.         }
  206.  
  207.  
  208.         private void ApplyDrive(float accel, float footbrake)
  209.         {
  210.  
  211.             float thrustTorque;
  212.             switch (m_CarDriveType)
  213.             {
  214.                 case CarDriveType.FourWheelDrive:
  215.                     thrustTorque = accel * (m_CurrentTorque / 4f);
  216.                     //print("Acceleration: " + accel + " Footbrake: " + footbrake  + "\nCurrent Torque: " + m_CurrentTorque + " Current Speed: " + CurrentSpeed);
  217.                     for (int i = 0; i < 4; i++)
  218.                     {
  219.                         m_WheelColliders[i].motorTorque = thrustTorque;
  220.                     }
  221.                     break;
  222.  
  223.                 case CarDriveType.FrontWheelDrive:
  224.                     thrustTorque = accel * (m_CurrentTorque / 2f);
  225.                     m_WheelColliders[0].motorTorque = m_WheelColliders[1].motorTorque = thrustTorque;
  226.                     break;
  227.  
  228.                 case CarDriveType.RearWheelDrive:
  229.                     thrustTorque = accel * (m_CurrentTorque / 2f);
  230.                     m_WheelColliders[2].motorTorque = m_WheelColliders[3].motorTorque = thrustTorque;
  231.                     break;
  232.  
  233.             }
  234.  
  235.             for (int i = 0; i < 4; i++)
  236.             {
  237.                 if (CurrentSpeed > 5 && Vector3.Angle(transform.forward, m_Rigidbody.velocity) < 50f)
  238.                 {
  239.                     m_WheelColliders[i].brakeTorque = m_BrakeTorque*footbrake;
  240.                 }
  241.                 else if (footbrake > 0)
  242.                 {
  243.                     m_WheelColliders[i].brakeTorque = 0f;
  244.                     m_WheelColliders[i].motorTorque = -m_ReverseTorque*footbrake;
  245.                 }
  246.             }
  247.         }
  248.  
  249.  
  250.         private void SteerHelper()
  251.         {
  252.             for (int i = 0; i < 4; i++)
  253.             {
  254.                 WheelHit wheelhit;
  255.                 m_WheelColliders[i].GetGroundHit(out wheelhit);
  256.                 if (wheelhit.normal == Vector3.zero)
  257.                     return; // wheels arent on the ground so dont realign the rigidbody velocity
  258.             }
  259.  
  260.             // this if is needed to avoid gimbal lock problems that will make the car suddenly shift direction
  261.             if (Mathf.Abs(m_OldRotation - transform.eulerAngles.y) < 10f)
  262.             {
  263.                 var turnadjust = (transform.eulerAngles.y - m_OldRotation) * m_SteerHelper;
  264.                 Quaternion velRotation = Quaternion.AngleAxis(turnadjust, Vector3.up);
  265.                 m_Rigidbody.velocity = velRotation * m_Rigidbody.velocity;
  266.             }
  267.             m_OldRotation = transform.eulerAngles.y;
  268.         }
  269.  
  270.  
  271.         // this is used to add more grip in relation to speed
  272.         private void AddDownForce()
  273.         {
  274.             m_WheelColliders[0].attachedRigidbody.AddForce(-transform.up*m_Downforce*
  275.                                                          m_WheelColliders[0].attachedRigidbody.velocity.magnitude);
  276.         }
  277.  
  278.  
  279.         // checks if the wheels are spinning and is so does three things
  280.         // 1) emits particles
  281.         // 2) plays tiure skidding sounds
  282.         // 3) leaves skidmarks on the ground
  283.         // these effects are controlled through the WheelEffects class
  284.         private void CheckForWheelSpin()
  285.         {
  286.             // loop through all wheels
  287.             for (int i = 0; i < 4; i++)
  288.             {
  289.                 WheelHit wheelHit;
  290.                 m_WheelColliders[i].GetGroundHit(out wheelHit);
  291.  
  292.                 // is the tire slipping above the given threshhold
  293.                 if (Mathf.Abs(wheelHit.forwardSlip) >= m_SlipLimit || Mathf.Abs(wheelHit.sidewaysSlip) >= m_SlipLimit)
  294.                 {
  295.                     m_WheelEffects[i].EmitTyreSmoke();
  296.  
  297.                     // avoiding all four tires screeching at the same time
  298.                     // if they do it can lead to some strange audio artefacts
  299.                     if (!AnySkidSoundPlaying())
  300.                     {
  301.                         m_WheelEffects[i].PlayAudio();
  302.                     }
  303.                     continue;
  304.                 }
  305.  
  306.                 // if it wasnt slipping stop all the audio
  307.                 if (m_WheelEffects[i].PlayingAudio)
  308.                 {
  309.                     m_WheelEffects[i].StopAudio();
  310.                 }
  311.                 // end the trail generation
  312.                 m_WheelEffects[i].EndSkidTrail();
  313.             }
  314.         }
  315.  
  316.         // crude traction control that reduces the power to wheel if the car is wheel spinning too much
  317.         private void TractionControl()
  318.         {
  319.             WheelHit wheelHit;
  320.             switch (m_CarDriveType)
  321.             {
  322.                 case CarDriveType.FourWheelDrive:
  323.                     // loop through all wheels
  324.                     for (int i = 0; i < 4; i++)
  325.                     {
  326.                         m_WheelColliders[i].GetGroundHit(out wheelHit);
  327.  
  328.                         AdjustTorque(wheelHit.forwardSlip);
  329.                     }
  330.                     break;
  331.  
  332.                 case CarDriveType.RearWheelDrive:
  333.                     m_WheelColliders[2].GetGroundHit(out wheelHit);
  334.                     AdjustTorque(wheelHit.forwardSlip);
  335.  
  336.                     m_WheelColliders[3].GetGroundHit(out wheelHit);
  337.                     AdjustTorque(wheelHit.forwardSlip);
  338.                     break;
  339.  
  340.                 case CarDriveType.FrontWheelDrive:
  341.                     m_WheelColliders[0].GetGroundHit(out wheelHit);
  342.                     AdjustTorque(wheelHit.forwardSlip);
  343.  
  344.                     m_WheelColliders[1].GetGroundHit(out wheelHit);
  345.                     AdjustTorque(wheelHit.forwardSlip);
  346.                     break;
  347.             }
  348.         }
  349.  
  350.  
  351.         private void AdjustTorque(float forwardSlip)
  352.         {
  353.             if (forwardSlip >= m_SlipLimit && m_CurrentTorque >= 0)
  354.             {
  355.                 m_CurrentTorque -= 10 * m_TractionControl;
  356.             }
  357.             else
  358.             {
  359.                 m_CurrentTorque += 10 * m_TractionControl;
  360.                 if (m_CurrentTorque > m_FullTorqueOverAllWheels)
  361.                 {
  362.                     m_CurrentTorque = m_FullTorqueOverAllWheels;
  363.                 }
  364.             }
  365.         }
  366.  
  367.  
  368.         private bool AnySkidSoundPlaying()
  369.         {
  370.             for (int i = 0; i < 4; i++)
  371.             {
  372.                 if (m_WheelEffects[i].PlayingAudio)
  373.                 {
  374.                     return true;
  375.                 }
  376.             }
  377.             return false;
  378.         }
  379.     }
  380. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement