RbBicycleSlopeSpeedManager.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using System;
  2. using Controller.Bicycle;
  3. using UnityEngine;
  4. using Wheels;
  5. namespace Phscs
  6. {
  7. [RequireComponent(typeof(RbBicycleController))]
  8. public class RbBicycleSlopeSpeedManager : MonoBehaviour
  9. {
  10. [Header("Game Objects")] public LerpSlopeCollider slopeCollider;
  11. private RbBicycleController bicycleController;
  12. [Header("Linear Adjustment")] [Range(0, 3)]
  13. public float speedFactorUphill;
  14. [Range(0, 3)] public float speedFactorDownhill;
  15. [Header("Lerp time at slope changes")] public float lerpTimeUphillStart; //TODO: maybe as factor of speed
  16. public float lerpTimeUphillEnd;
  17. public float lerpTimeDownhillStart;
  18. public float lerpTimeDownhillEnd;
  19. private const float THRESHOLD = 0.05f;
  20. private const float SLOPE_CHANGE_THRESHOLD = 2f;
  21. private float t0;
  22. private float v0;
  23. private readonly float g = UnityEngine.Physics.gravity.y;
  24. private float alpha;
  25. private float alphaBefore;
  26. private int direction;
  27. private int directionBefore;
  28. public float? AdjustedSpeed { private set; get; }
  29. public float GradientDeg => alpha;
  30. private void Start()
  31. {
  32. bicycleController = GetComponent<RbBicycleController>();
  33. slopeCollider.OnSlopeChanged += delegate(float timestamp, float slopeDeg)
  34. {
  35. alphaBefore = alpha;
  36. alpha = slopeDeg;
  37. if (Mathf.Abs(alphaBefore - alpha) < SLOPE_CHANGE_THRESHOLD) return;
  38. t0 = timestamp;
  39. v0 = bicycleController.CurrentSpeed;
  40. directionBefore = direction;
  41. };
  42. }
  43. private void OnGUI()
  44. {
  45. GUI.TextField(new Rect(150, 10, 200, 20), $"direction: {direction}, directionBefore: {directionBefore}");
  46. }
  47. private void FixedUpdate()
  48. {
  49. direction = Math.Abs(alpha) > THRESHOLD ? slopeCollider.SlopeDirection : 0;
  50. if (direction == 0 && directionBefore == 0)
  51. {
  52. AdjustedSpeed = null;
  53. return;
  54. }
  55. var t = Time.fixedTime - t0;
  56. var gradient = Mathf.Tan(direction * alpha * Mathf.Deg2Rad);
  57. var gradientBefore = Mathf.Tan(directionBefore * alphaBefore * Mathf.Deg2Rad);
  58. var mass = bicycleController.rigidBody.mass;
  59. float calculatedSpeed;
  60. var sensedSpeed = bicycleController.CurrentSpeedSensed;
  61. if (directionBefore == 0 && direction == 1) //flat to uphill
  62. {
  63. calculatedSpeed = BicyclePhysics.SpeedAtGradientForSpeedAtFlat(sensedSpeed, mass, gradient) * speedFactorUphill;
  64. AdjustedSpeed = Mathf.Lerp(sensedSpeed, calculatedSpeed, t / lerpTimeUphillStart);
  65. }
  66. else if (directionBefore == 1 && direction == 0) //uphill to flat
  67. {
  68. calculatedSpeed = BicyclePhysics.SpeedAtGradientForSpeedAtFlat(sensedSpeed, mass, gradientBefore) * speedFactorUphill;
  69. AdjustedSpeed = Mathf.Lerp(calculatedSpeed, sensedSpeed , t / lerpTimeUphillEnd);
  70. }
  71. else if (directionBefore == 0 && direction == -1) //flat to downhill
  72. {
  73. calculatedSpeed = BicyclePhysics.SpeedAtGradientForSpeedAtFlat(sensedSpeed, mass, gradient) * speedFactorDownhill;
  74. AdjustedSpeed = Mathf.Lerp(sensedSpeed, calculatedSpeed, t / lerpTimeDownhillStart);
  75. }
  76. else if (directionBefore == -1 && direction == 0) //downhill to flat
  77. {
  78. calculatedSpeed = BicyclePhysics.SpeedAtGradientForSpeedAtFlat(sensedSpeed, mass, gradientBefore) * speedFactorDownhill;
  79. AdjustedSpeed = Mathf.Lerp(calculatedSpeed, sensedSpeed, t / lerpTimeDownhillEnd);
  80. }
  81. }
  82. }
  83. }