Advertisement
Guest User

Untitled

a guest
Nov 21st, 2014
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.25 KB | None | 0 0
  1. //========================================================================================================================
  2. // Edy Vehicle Physics - (c) Angel Garcia "Edy" - Oviedo, Spain
  3. // http://www.edy.es/dev/vehicle-physics
  4. //
  5. // Terms & Conditions:
  6. // - Use for unlimited time, any number of projects, royalty-free.
  7. // - Keep the copyright notices on top of the source files.
  8. // - Resale or redistribute as anything except a final product to the end user (asset / library / engine / middleware / etc.) is not allowed.
  9. // - Put me (Angel Garcia "Edy") in your game's credits as author of the vehicle physics.
  10. //
  11. // Bug reports, improvements to the code, suggestions on further developments, etc are always welcome.
  12. // Unity forum user: Edy
  13. //========================================================================================================================
  14. //
  15. // CarControl
  16. //
  17. // Main script for controlling and configuring the vehicle. All parameters that affect the behavior & handling
  18. // are defined here (except suspension parameters: spring, damper, distance, radius, which are configured on each wheel).
  19. //
  20. //========================================================================================================================
  21. using UnityEngine;
  22.  
  23. public class CarControl : BMBSingleton<CarControl>
  24. {
  25.  
  26. // Objetos controlados
  27.  
  28. public CarWheel WheelFL;
  29. public CarWheel WheelFR;
  30. public CarWheel WheelRL;
  31. public CarWheel WheelRR;
  32. public CarAntiRollBar AntiRollFront;
  33. public CarAntiRollBar AntiRollRear;
  34. public Transform CenterOfMass;
  35.  
  36. // Curvas de fricción de las ruedas
  37. public CarFrictionCurve ForwardWheelFriction;
  38. public CarFrictionCurve SidewaysWheelFriction;
  39. public bool optimized = false; // En modo optimizado los parámetros de las curvas de fricción no se pueden cambiar en tiempo real (no responden adecuadamente).
  40.  
  41. // Parámetros de entrada
  42.  
  43. public bool readUserInput = false; // Reads user input itself instead of depending of externally provided input. This flag is automatically disabled when the car is controlled from a CarMain script.
  44. public bool reverseRequiresStop = false; // Applicable only when readUserInput is true. If the car is controlled from a CarMain script then the global CarMain.reverseRequiresStop flag applies.
  45. public float steerInput = 0.0f;
  46. public float motorInput = 0.0f;
  47. public float brakeInput = 0.0f;
  48. public float handbrakeInput = 0.0f;
  49. public int gearInput = 1;
  50.  
  51. // Parámetros de rendimiento y comportamiento
  52.  
  53. public float steerMax = 45.0f;
  54. public float motorMax = 1.0f; // Cantidad máxima de slip de aceleración antes de TC
  55. public float brakeMax = 1.0f; // Cantidad máxima de slip de frenado antes de ABS
  56.  
  57. public float autoSteerLevel = 1.0f; // ESP
  58. public bool autoMotorMax = true; // TC
  59. public bool autoBrakeMax = true; // ABS
  60. public float antiRollLevel = 1.0f; // Barras estabilizadoras
  61.  
  62. public float motorPerformancePeak = 5.0f; // m/s de aceleración máxima en modo 4x4. En tracción simple es necesario subir el motorForceFactor
  63. public float motorForceFactor = 1.0f;
  64. public float motorBalance = 0.5f; // 0.0 = tracción delantera, 1.0 = tracción trasera, 0.5 = 4x4.
  65. public float brakeForceFactor = 1.5f;
  66. public float brakeBalance = 0.5f; // 0.0 = todo adelante, 1.0 = todo atrás, 0.5 = mismo nivel.
  67.  
  68. public float sidewaysDriftFriction = 0.35f;
  69. public float staticFrictionMax = 1500.0f; // Control de fricción - ver CarWheel.
  70. public float frontSidewaysGrip = 1.0f;
  71. public float rearSidewaysGrip = 1.0f;
  72.  
  73. // Parámetros de configuración
  74.  
  75. public bool serviceMode = false; // Si está activado se asignan los parámetros de grip tal cual. Permite hacer las pruebas de las curvas de fricción.
  76.  
  77. public float airDrag = 3.0f * 2.2f; // Coeficiente aerodinámico (ej. corvette 0.30) * Area frontal
  78. public float frictionDrag = 30.0f; // 30 veces la resistencia del aire (así airDrag será más importante a partir de 30 m/s = 100 Km/h)
  79.  
  80. public float rollingFrictionSlip = 0.075f;
  81.  
  82. // MODO EXPERIMENTAL V3:
  83. // - Reduce la tracción a medida que se aproxima a la velocidad máxima. Alcanzando ésta la tracción es 0.
  84.  
  85. public bool tractionV3 = false;
  86. public float maxSpeed = 40.0f;
  87.  
  88.  
  89. // ------------------------------------------------
  90. // Datos privados + telemetría
  91.  
  92. private bool m_brakeRelease = false;
  93. private float m_motorSlip = 0.0f;
  94. private float m_brakeSlip = 0.0f;
  95. private float m_frontMotorSlip = 0.0f;
  96. private float m_frontBrakeSlip = 0.0f;
  97. private float m_rearMotorSlip = 0.0f;
  98. private float m_rearBrakeSlip = 0.0f;
  99. private float m_steerL = 0.0f;
  100. private float m_steerR = 0.0f;
  101. private float m_steerAngleMax = 0.0f;
  102. private float m_maxRollAngle = 45.0f;
  103. private float throttle;
  104. //JOHN
  105. public enum PlatformControllerType
  106. {
  107. Accel,
  108. Mouse,
  109. Keyboard,
  110. Analogue,
  111.  
  112. };
  113.  
  114. public PlatformControllerType SelectedControllerType;
  115.  
  116.  
  117.  
  118. // JOHN
  119. public float forwardValue;
  120. public float reverseValue;
  121. public float selectedSteerInputAmount;
  122.  
  123.  
  124. public string getGear( )
  125. {
  126. return gearInput > 0 ? "D" : gearInput < 0 ? "R" : "N";
  127. }
  128.  
  129. public float getMotor( )
  130. {
  131. return motorInput;
  132. }
  133.  
  134. public float getBrake( )
  135. {
  136. return brakeInput;
  137. }
  138.  
  139. public float getHandBrake( )
  140. {
  141. return handbrakeInput;
  142. }
  143.  
  144. public float getSteerL( )
  145. {
  146. return m_steerL;
  147. }
  148.  
  149. public float getSteerR( )
  150. {
  151. return m_steerR;
  152. }
  153.  
  154. public float getMaxRollAngle( )
  155. {
  156. return m_maxRollAngle;
  157. }
  158.  
  159. void OnEnable( )
  160. {
  161. ApplyEnabled(WheelFL, true);
  162. ApplyEnabled(WheelFR, true);
  163. ApplyEnabled(WheelRL, true);
  164. ApplyEnabled(WheelRR, true);
  165. }
  166.  
  167. void OnDisable( )
  168. {
  169. ApplyEnabled(WheelFL, false);
  170. ApplyEnabled(WheelFR, false);
  171. ApplyEnabled(WheelRL, false);
  172. ApplyEnabled(WheelRR, false);
  173. }
  174.  
  175. //VCAnalogJoystickBase vcSteer, vcDrive;
  176. //VCButtonBase accelButton, reverseButton;
  177. void Start( )
  178. {
  179.  
  180.  
  181. #if(UNITY_ANDROID)
  182. SelectedControllerType = PlatformControllerType.Accel;
  183. #endif
  184. #if(UNITY_IOS)
  185. SelectedControllerType = PlatformControllerType.Accel;
  186. #endif
  187. //#if(UNITY_EDITOR)
  188. // SelectedControllerType = PlatformControllerType.Keyboard;
  189. //#endif
  190. //#if(UNITY_WEBPLAYER)
  191. // SelectedControllerType = PlatformControllerType.Keyboard;
  192. //#endif
  193.  
  194. // Centro de Masas (CoM)
  195. // LocalScale es necesario para aplicar cualquier escalado que se haya aplicado al modelo.
  196.  
  197. if (CenterOfMass)
  198. rigidbody.centerOfMass = new Vector3(CenterOfMass.localPosition.x * transform.localScale.x, CenterOfMass.localPosition.y * transform.localScale.y, CenterOfMass.localPosition.z * transform.localScale.z);
  199.  
  200. // Punto de equilibrio lateral (estimado)
  201. WheelCollider WheelC = WheelFL.GetComponent<WheelCollider>() as WheelCollider;
  202. Vector3 V = rigidbody.centerOfMass - transform.InverseTransformPoint(WheelC.transform.position);
  203. float h = Mathf.Abs((V.y + WheelC.radius + WheelC.suspensionDistance / 2.0f) * transform.localScale.y);
  204. float l = Mathf.Abs(V.x * transform.localScale.x);
  205. m_maxRollAngle = Mathf.Atan2(l, h) * Mathf.Rad2Deg;
  206.  
  207. // Otros datos
  208.  
  209. rigidbody.maxAngularVelocity = 10;
  210. rigidbody.useConeFriction = false;
  211.  
  212. // En modo optimizado aplicar los parámetros de las ruedas ahora, entonces recalcular los datos costosos
  213.  
  214. if (!optimized) return;
  215. ApplyCommonParameters(WheelFL);
  216. ApplyCommonParameters(WheelFR);
  217. ApplyCommonParameters(WheelRL);
  218. ApplyCommonParameters(WheelRR);
  219. WheelFL.RecalculateStuff();
  220. WheelFR.RecalculateStuff();
  221. WheelRL.RecalculateStuff();
  222. WheelRR.RecalculateStuff();
  223. }
  224.  
  225. void PressedGas( )
  226. {
  227. forwardValue = 1;
  228. }
  229.  
  230. void ReleasedGas( )
  231. {
  232. forwardValue = 0;
  233. }
  234.  
  235. void PressedBrake( )
  236. {
  237. reverseValue = 1;
  238. }
  239.  
  240. void ReleasedBrake( )
  241. {
  242. reverseValue = 0;
  243. }
  244.  
  245. void SteerLeft( )
  246. {
  247. steerInput = -1;
  248. selectedSteerInputAmount = -1;
  249. }
  250.  
  251. void ReleasedSteer( )
  252. {
  253. steerInput = 0;
  254. selectedSteerInputAmount = 0;
  255. }
  256.  
  257. void SteerRight( )
  258. {
  259. steerInput = 1;
  260. selectedSteerInputAmount = 1;
  261. }
  262.  
  263. void FixedUpdate( )
  264. {
  265. switch (SelectedControllerType)
  266. {
  267. case CarControl.PlatformControllerType.Accel:
  268. {
  269. steerInput = P_HUD.I.steeringWheel._CurrentFloat;
  270. selectedSteerInputAmount = steerInput;
  271. }
  272. break;
  273. case CarControl.PlatformControllerType.Keyboard:
  274. {
  275. steerInput = Input.GetAxis("Horizontal");
  276. forwardValue = Mathf.Clamp(Input.GetAxis("Vertical"), 0, 1f);
  277. reverseValue = -1 * Mathf.Clamp(Input.GetAxis("Vertical"), -1f, 0);
  278. selectedSteerInputAmount = steerInput;
  279. }
  280. break;
  281. case CarControl.PlatformControllerType.Mouse:
  282. {
  283. steerInput = ((Input.mousePosition.x / Screen.width) * 2) - 1;
  284. forwardValue = Mathf.Clamp(Input.GetAxis("Vertical"), 0, 1);
  285. reverseValue = -1 * Mathf.Clamp(Input.GetAxis("Vertical"), -1, 0);
  286. selectedSteerInputAmount = steerInput;
  287. }
  288. break;
  289. }
  290. //======================================================================
  291. // 1. Aplicar parámetros a las ruedas
  292. //======================================================================
  293. // Parámetros de las ruedas que se establecen una vez en el script de control para no tener que ir rueda por rueda
  294.  
  295. ApplyCommonParameters(WheelFL);
  296. ApplyCommonParameters(WheelFR);
  297. ApplyCommonParameters(WheelRL);
  298. ApplyCommonParameters(WheelRR);
  299.  
  300. // Pámetros para ruedas individuales según configuración actual
  301.  
  302. ApplyFrontParameters(WheelFL);
  303. ApplyFrontParameters(WheelFR);
  304. ApplyRearParameters(WheelRL);
  305. ApplyRearParameters(WheelRR);
  306.  
  307. //======================================================================
  308. // 2. Aplicar tracción / frenado
  309. //======================================================================
  310.  
  311. m_motorSlip = motorInput * motorMax;
  312. m_brakeSlip = brakeInput * brakeMax;
  313.  
  314. if (gearInput == 0)
  315. m_motorSlip = 0;
  316. else if (gearInput < 0)
  317. m_motorSlip = -m_motorSlip;
  318.  
  319. // Balance de tracción
  320.  
  321. if (serviceMode)
  322. {
  323. m_frontMotorSlip = m_motorSlip;
  324. m_rearMotorSlip = m_motorSlip;
  325. }
  326. else if (motorBalance >= 0.5f)
  327. { // reducir tracción adelante
  328. m_frontMotorSlip = m_motorSlip * (1.0f - motorBalance) * 2.0f;
  329. m_rearMotorSlip = m_motorSlip;
  330. }
  331. else
  332. { // Reducir tracción atrás
  333. m_frontMotorSlip = m_motorSlip;
  334. m_rearMotorSlip = m_motorSlip * motorBalance * 2.0f;
  335. }
  336.  
  337. // Balance de frenado
  338.  
  339. if (serviceMode)
  340. {
  341. m_frontBrakeSlip = m_brakeSlip;
  342. m_rearBrakeSlip = m_brakeSlip;
  343. }
  344. else if (brakeBalance >= 0.5f)
  345. { // reducir frenos adelante
  346. m_frontBrakeSlip = m_brakeSlip * (1.0f - brakeBalance) * 2.0f;
  347. m_rearBrakeSlip = m_brakeSlip;
  348. }
  349. else
  350. { // Reducir frenos atrás
  351. m_frontBrakeSlip = m_brakeSlip;
  352. m_rearBrakeSlip = m_brakeSlip * brakeBalance * 2.0f;
  353. }
  354.  
  355. ApplyTraction(WheelFL, m_frontMotorSlip, m_frontBrakeSlip, 0.0f);
  356. ApplyTraction(WheelFR, m_frontMotorSlip, m_frontBrakeSlip, 0.0f);
  357. ApplyTraction(WheelRL, m_rearMotorSlip, m_rearBrakeSlip, handbrakeInput);
  358. ApplyTraction(WheelRR, m_rearMotorSlip, m_rearBrakeSlip, handbrakeInput);
  359.  
  360. //======================================================================
  361. // 3. Aplicar dirección
  362. //======================================================================
  363.  
  364. // autoSteerLevel determina el ángulo en el que las ruedas ofrecen la máxima fuerza de giro (peakSlip) a la velocidad actual.
  365. // Se coge como referencia una rueda cualquiera delantera.
  366.  
  367. if (autoSteerLevel > 0.0f)
  368. {
  369. float peakSlip = WheelFL.getSidewaysPeakSlip();
  370. float forwardSpeed = Mathf.Abs(transform.InverseTransformDirection(rigidbody.velocity).z * autoSteerLevel);
  371.  
  372. if (forwardSpeed > peakSlip)
  373. m_steerAngleMax = 90.0f - Mathf.Acos(peakSlip / forwardSpeed) * Mathf.Rad2Deg;
  374. else
  375. m_steerAngleMax = steerMax;
  376. }
  377. else
  378. m_steerAngleMax = steerMax;
  379.  
  380. // La dirección de giro de cada rueda se calcula en Update para que se visualice con suavidad,
  381. // incluso en cámara lenta.
  382.  
  383. WheelFL.getWheelCollider().steerAngle = m_steerL;
  384. WheelFR.getWheelCollider().steerAngle = m_steerR;
  385.  
  386. //======================================================================
  387. // 4. Fuerzas de resistencia
  388. //======================================================================
  389.  
  390. // Resistencia aerodinámica (drag) y resistencia a rodar (rr)
  391. //
  392. // Fdrag = -Cdrag * V * |V|
  393. // Frr = -Crr * V
  394.  
  395. // Cdrag = 0.5 * Cd * A * rho
  396. // Cd = coeficiente aerodinámico (ej. corvette 0.30)
  397. // A = área frontal del vehículo
  398. // rho = densidad del aire = 1.29 kg/m3
  399. //
  400. // Crr = 30 veces Cdrag (así Fdrag será más importante a partir de 30 m/s = 100 Km/h)
  401.  
  402. if (!serviceMode)
  403. {
  404. float Cdrag = 0.5f * airDrag * 1.29f; // * (motorMax+1) / 2;
  405. float Crr = frictionDrag * Cdrag;
  406.  
  407. Vector3 Fdrag = -Cdrag * rigidbody.velocity * rigidbody.velocity.magnitude;
  408. Vector3 Frr = -Crr * rigidbody.velocity;
  409.  
  410. rigidbody.AddForce(Fdrag + Frr);
  411. }
  412.  
  413. //======================================================================
  414. // 5. Ajustes técnicos adicionales
  415. //======================================================================
  416.  
  417. // Barras estabilizadoras
  418.  
  419. if (AntiRollFront)
  420. AntiRollFront.AntiRollFactor = antiRollLevel;
  421. if (AntiRollRear)
  422. AntiRollRear.AntiRollFactor = antiRollLevel;
  423. }
  424.  
  425. void Update( )
  426. {
  427. // Read user input if specified
  428.  
  429. if (readUserInput)
  430. m_brakeRelease = CarMain.SendInput(this, reverseRequiresStop, m_brakeRelease);
  431.  
  432. // Calcular los ángulos de giro de las ruedas para que los cambios de dirección se visualicen con suavemente,
  433. // incluso en cámara lenta. FixedUpdate coge los valores que haya en el momento.
  434.  
  435. CalculateSteerAngles();
  436. }
  437.  
  438. void ApplyEnabled(CarWheel Wheel, bool enable)
  439. {
  440. // Necesario comprobar con null, ya que el OnDisable se invoca al finalizar la aplicación,
  441. // y el objeto puede no estar ya disponible aunque su referencia sea no nula.
  442.  
  443. if (Wheel != null)
  444. Wheel.enabled = enable;
  445. }
  446.  
  447. void ApplyCommonParameters(CarWheel Wheel)
  448. {
  449. Wheel.ForwardWheelFriction = ForwardWheelFriction;
  450. Wheel.SidewaysWheelFriction = SidewaysWheelFriction;
  451. Wheel.brakeForceFactor = brakeForceFactor;
  452. Wheel.motorForceFactor = motorForceFactor;
  453. Wheel.performancePeak = motorPerformancePeak;
  454. Wheel.sidewaysDriftFriction = sidewaysDriftFriction;
  455. Wheel.staticFrictionMax = staticFrictionMax;
  456.  
  457. Wheel.serviceMode = serviceMode;
  458. Wheel.optimized = optimized;
  459. }
  460.  
  461. void ApplyFrontParameters(CarWheel Wheel)
  462. {
  463. Wheel.sidewaysForceFactor = frontSidewaysGrip;
  464. }
  465.  
  466. void ApplyRearParameters(CarWheel Wheel)
  467. {
  468. Wheel.sidewaysForceFactor = rearSidewaysGrip;
  469. }
  470.  
  471. void ApplyTraction(CarWheel Wheel, float motorSlip, float brakeSlip, float handBrakeInput)
  472. {
  473. float slipPeak = Wheel.getForwardPeakSlip();
  474. float slipMax = Wheel.getForwardMaxSlip();
  475.  
  476. WheelHit Hit = new WheelHit();
  477. float slip;
  478.  
  479. // Tracción
  480.  
  481. float motor = Mathf.Abs(motorSlip); // motor = [0..motorMax]
  482.  
  483. bool grounded = Wheel.getWheelCollider().GetGroundHit(out Hit);
  484.  
  485. if (grounded)
  486. {
  487. Quaternion steerRot = Quaternion.AngleAxis(Wheel.getWheelCollider().steerAngle, Wheel.transform.up);
  488. Vector3 wheelDir = steerRot * Wheel.transform.forward;
  489.  
  490. Vector3 pointV = rigidbody.GetPointVelocity(Hit.point);
  491.  
  492. if (Hit.collider.attachedRigidbody)
  493. pointV -= Hit.collider.attachedRigidbody.GetPointVelocity(Hit.point);
  494.  
  495. float v = Mathf.Abs(Vector3.Dot(pointV, wheelDir));
  496.  
  497. if (v + slipPeak <= motorMax)
  498. {
  499. slip = motor - v;
  500.  
  501. if (slip < 0)
  502. slip = 0;
  503. else if (autoMotorMax && slip > slipPeak)
  504. slip = slipPeak;
  505. }
  506. else
  507. {
  508. float maxSlip;
  509.  
  510. if (tractionV3)
  511. maxSlip = Mathf.Lerp(slipPeak, 0, Mathf.InverseLerp(motorMax - slipPeak, maxSpeed, v));
  512. else
  513. maxSlip = slipPeak;
  514. slip = maxSlip * motor / motorMax;
  515. }
  516.  
  517. if (motorSlip < 0)
  518. slip = -slip;
  519. }
  520. else
  521. slip = motorSlip;
  522.  
  523. // Frenos
  524.  
  525. if (autoBrakeMax && brakeSlip > slipPeak)
  526. brakeSlip = slipPeak;
  527.  
  528. brakeSlip = Mathf.Max(brakeSlip, handBrakeInput * slipMax);
  529.  
  530. if (motorInput == 0.0f)
  531. brakeSlip += rollingFrictionSlip / brakeForceFactor;
  532.  
  533. if (!grounded)
  534. { // Las ruedas en el aire se frenan en función de su velocidad
  535. float omega = Wheel.getWheelCollider().rpm * Mathf.Deg2Rad;
  536. brakeSlip += omega * omega * 0.0008f / brakeForceFactor;
  537. }
  538.  
  539. Wheel.motorInput = slip;
  540. Wheel.brakeInput = brakeSlip;
  541. }
  542.  
  543. void CalculateSteerAngles( )
  544. {
  545. // -------- Giro de dirección ruedas delanteras
  546.  
  547. // Calcular el ángulo de ambas ruedas para el giro perfecto.
  548. // Se asume que las distancias entre las ruedas son iguales delante-detrás e izquierda-derecha.
  549. // Valores máximos de giro: -90..+90
  550.  
  551. float B = (WheelFL.transform.position - WheelFR.transform.position).magnitude;
  552. float H = (WheelFR.transform.position - WheelRR.transform.position).magnitude;
  553.  
  554. if (steerInput > 0.0f)
  555. { // Giro a la derecha
  556. m_steerR = steerMax * steerInput;
  557. if (m_steerR > m_steerAngleMax)
  558. m_steerR = m_steerAngleMax;
  559. m_steerL = Mathf.Rad2Deg * Mathf.Atan(1.0f / (Mathf.Tan((90 - m_steerR) * Mathf.Deg2Rad) + B / H));
  560. }
  561. else if (steerInput < 0.0f)
  562. { // Giro a la izquierda
  563. m_steerL = steerMax * steerInput;
  564. if (m_steerL < -m_steerAngleMax)
  565. m_steerL = -m_steerAngleMax;
  566.  
  567. m_steerR = -Mathf.Rad2Deg * Mathf.Atan(1.0f / (Mathf.Tan((90 + m_steerL) * Mathf.Deg2Rad) + B / H));
  568. }
  569. else
  570. {
  571. m_steerL = 0;
  572. m_steerR = 0;
  573. }
  574. }
  575.  
  576. void Drive(float throttleChangeSpeed, float throttle)
  577. {
  578. motorInput = Mathf.MoveTowards(motorInput, throttle, throttleChangeSpeed * Time.deltaTime);
  579. gearInput = 1;
  580. brakeInput = 0;
  581. handbrakeInput = 0.0f;
  582. }
  583. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement