Guest User

Untitled

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