RbBicycleController.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System;
  2. using UnityEngine;
  3. using Wheels;
  4. namespace Controller.Bicycle
  5. {
  6. public class RbBicycleController : BicycleControllerBaseBehaviour, IBicycleController
  7. {
  8. #region Variables
  9. private const float THRESHOLD_GRADIENT_ZERO = .05f;
  10. private Transform rbTransform;
  11. private float currentSteerAngle;
  12. private float currentLeaningAngle;
  13. private float currentSpeedSensed;
  14. private float currentSpeedAdjusted;
  15. //private float previousSpeedAdjusted;
  16. //private float maxDifToPreviousSpeedDueToGradientPerSecond = 2f;
  17. [Header("Slope Impact")] public bool adjustSpeedToSlope = true;
  18. public Vector3 Forward => rbTransform.forward;
  19. public Vector3 Right => -rbTransform.right;
  20. public Vector3 Up => rbTransform.up;
  21. public BicycleControllerMode ControllerMode
  22. {
  23. get => controllerMode;
  24. set => controllerMode = value;
  25. }
  26. public float CurrentSpeed
  27. {
  28. get => adjustSpeedToSlope ? currentSpeedAdjusted : currentSpeedSensed;
  29. set => currentSpeedSensed = Mathf.Clamp(value, 0, maxSpeed);
  30. }
  31. public float CurrentSpeedKph => CurrentSpeed * 3.6f;
  32. public float CurrentSteerAngle
  33. {
  34. get => currentSteerAngle;
  35. set => currentSteerAngle = Mathf.Clamp(value, -maxSteeringAngle, maxSteeringAngle);
  36. }
  37. public float CurrentLeaningAngle
  38. {
  39. get => currentLeaningAngle;
  40. set
  41. {
  42. //don't lean while standing / walking to bike
  43. if (rigidBody.velocity.magnitude < .5f) return;
  44. currentLeaningAngle = Mathf.Clamp(value, -maxLeaningAngle, maxLeaningAngle);
  45. }
  46. }
  47. public Vector3 RigidBodyVelocity => rigidBody.velocity;
  48. #endregion
  49. private void Awake()
  50. {
  51. rbTransform = rigidBody.transform;
  52. rigidBody.freezeRotation = true;
  53. rigidBody.centerOfMass = centerOfMass.position;
  54. }
  55. private void FixedUpdate()
  56. {
  57. //rigidBody.isKinematic = currentSpeed <= THRESHOLD_STANDING;
  58. ApplyVelocity();
  59. ApplySteerAngleAndRotation();
  60. }
  61. private void ApplyVelocity()
  62. {
  63. var targetVelocity = CalculateTargetVelocity();
  64. var velocityChange = targetVelocity - rigidBody.velocity;
  65. velocityChange.y = 0;
  66. rigidBody.AddForce(velocityChange, ForceMode.VelocityChange);
  67. }
  68. private Vector3 CalculateTargetVelocity()
  69. {
  70. AdjustSpeedToGradientIfNeeded();
  71. var tv = new Vector3(0, 0, currentSpeedAdjusted);
  72. tv = rbTransform.TransformDirection(tv);
  73. return tv;
  74. }
  75. private void AdjustSpeedToGradientIfNeeded()
  76. {
  77. //previousSpeedAdjusted = currentSpeedAdjusted;
  78. var bikeAngle = rbTransform.localRotation.eulerAngles.x;
  79. if (!adjustSpeedToSlope || Mathf.Abs(bikeAngle) <= THRESHOLD_GRADIENT_ZERO)
  80. {
  81. currentSpeedAdjusted = currentSpeedSensed;
  82. return;
  83. }
  84. if (bikeAngle > 180)
  85. {
  86. bikeAngle -= 360f;
  87. }
  88. else if (bikeAngle < -180)
  89. {
  90. bikeAngle = 360f - bikeAngle;
  91. }
  92. var gradientDeg = -bikeAngle;
  93. var gradient = Mathf.Tan(gradientDeg * Mathf.Deg2Rad);
  94. //var maxDif = maxDifToPreviousSpeedDueToGradientPerSecond * Time.deltaTime;
  95. //var dif = Math.Abs(currentSpeedSensed)
  96. currentSpeedAdjusted = gradient < 0
  97. ? currentSpeedSensed * 1.5f
  98. : BicyclePhysics.SpeedAtGradientForSpeedAtFlat(currentSpeedSensed, rigidBody.mass,
  99. gradient); //TODO make work for downhill - and lerp between the speeds!
  100. }
  101. private void ApplySteerAngleAndRotation()
  102. {
  103. //don't lean and rotate when veeeeeery sloooow/standing. Otherwise bike will rotate already
  104. if (CurrentSpeed < 0.3f) //ca 1 km/h
  105. {
  106. CurrentSteerAngle = 0;
  107. CurrentLeaningAngle = 0;
  108. }
  109. var sumMode = controllerMode.weightLeaning + controllerMode.weightSteering;
  110. var calculatedSteerAngle = (controllerMode.weightSteering * CurrentSteerAngle +
  111. controllerMode.weightLeaning + currentLeaningAngle) /
  112. sumMode; //TODO: maybe define what leaning angle means as steering angle;
  113. var r = rbTransform.localRotation.eulerAngles;
  114. float rectifiedZ;
  115. if (r.z > 180f)
  116. {
  117. rectifiedZ = -360 + r.z;
  118. }else if (r.z < -180f)
  119. {
  120. rectifiedZ = 360 + r.z;
  121. }
  122. else
  123. {
  124. rectifiedZ = r.z;
  125. }
  126. var leanDif = -CurrentLeaningAngle - rectifiedZ;
  127. rbTransform.localRotation =
  128. Quaternion.Euler(r + new Vector3(0, calculatedSteerAngle, leanDif) * Time.fixedDeltaTime);
  129. }
  130. }
  131. }