Advertisement
sphinx2001

CarConroller

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