BicycleController.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. public enum VelocityMode
  6. {
  7. ApplySpeedToRigidBody,
  8. ApplyTorqueToWheelCollider,
  9. ApplySpeedToWheelCollider,
  10. Keyboard
  11. }
  12. public class BicycleController : MonoBehaviour
  13. {
  14. [Header("GameObjects")] public GameObject rearWheel;
  15. public GameObject frontWheel;
  16. public GameObject crank;
  17. public GameObject bike;
  18. //public GameObject pedalL;
  19. //public GameObject pedalR;
  20. public GameObject fork;
  21. public Transform centerOfMass;
  22. [Header("Configuration")] public VelocityMode velocityMode = VelocityMode.ApplySpeedToWheelCollider;
  23. [Header("Values")] public float oneRotationSpeed = 2.7f;
  24. public float crankMultiplier = 2f;
  25. public List<AxleInfo> axleInfos; // the information about each individual axle
  26. public float maxMotorTorque = 12f; // maximum torque the motor can apply to wheel
  27. public float maxSteeringAngle = 5f; // maximum steer angle the wheel can have
  28. [Range(0, 1)] public float relativeLeanAmount = 0.01f;
  29. public Transform leftWheels;
  30. public Transform rightWheels;
  31. private float currentSteerAngle = 0f;
  32. private float currentSpeed = 0f;
  33. private float currentLeaningAngle = 0f;
  34. public float rotSpeed = 10;
  35. private Vector3[] wheelPositions;
  36. public Rigidbody rb;
  37. private Quaternion startForkRot;
  38. private Vector3 upDirection = Vector3.up;
  39. // Start is called before the first frame update
  40. void Start()
  41. {
  42. //rb = GetComponent<Rigidbody>();
  43. rb.centerOfMass = centerOfMass.localPosition;
  44. //startForkRot = fork.transform.localRotation;
  45. wheelPositions = new Vector3[axleInfos.Count];
  46. for (int i = 0; i < axleInfos.Count; i++)
  47. {
  48. wheelPositions[i] = axleInfos[i].wheel.center;
  49. }
  50. }
  51. private void OnGUI()
  52. {
  53. if (velocityMode == VelocityMode.Keyboard)
  54. {
  55. GUI.TextField(new Rect(114, 10, 160, 20), $"Simulated speed {currentSpeed * 3.6} km/h");
  56. }
  57. }
  58. // Update is called once per frame
  59. void Update()
  60. {
  61. if (velocityMode == VelocityMode.Keyboard)
  62. {
  63. currentSpeed = Input.GetAxis("Vertical") * 8.3333f;
  64. currentSteerAngle = Input.GetAxis("Horizontal") * maxSteeringAngle;
  65. }
  66. RotateMeshes();
  67. //RotateFork();
  68. Debug.Log("rotation: " + currentSteerAngle);
  69. }
  70. public void FixedUpdate()
  71. {
  72. ApplyWheelForce();
  73. Lean();
  74. //RotateStraight();
  75. }
  76. void RotateMeshes()
  77. {
  78. //RotateObject(crank, 1);
  79. //RotateObject(pedalL, -1);
  80. //RotateObject(pedalR, -1);
  81. RotateObject(rearWheel, crankMultiplier);
  82. RotateObject(frontWheel, crankMultiplier);
  83. }
  84. void RotateFork()
  85. {
  86. fork.transform.localRotation = startForkRot;
  87. fork.transform.RotateAround(fork.transform.position, fork.transform.up, maxSteeringAngle * currentSteerAngle);
  88. }
  89. void Lean()
  90. {
  91. upDirection = Vector3.Normalize(Vector3.up + transform.right *
  92. (maxSteeringAngle * relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude) / 100);
  93. }
  94. void ApplyWheelForce()
  95. {
  96. float motor = maxMotorTorque;
  97. float steering = maxSteeringAngle * currentSteerAngle;
  98. leftWheels.localPosition = -Vector3.up * (relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude);
  99. rightWheels.localPosition = Vector3.up * (relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude);
  100. if (velocityMode == VelocityMode.ApplySpeedToRigidBody)
  101. {
  102. //TODO: figure out what to do when going upwards?
  103. rb.velocity = bike.transform.forward * currentSpeed;
  104. }
  105. foreach (AxleInfo axleInfo in axleInfos)
  106. {
  107. if (axleInfo.steering)
  108. {
  109. axleInfo.wheel.steerAngle = steering;
  110. }
  111. if (velocityMode == VelocityMode.ApplySpeedToWheelCollider || velocityMode == VelocityMode.Keyboard)
  112. {
  113. if (axleInfo.motor && rb.velocity.magnitude < currentSpeed)
  114. {
  115. axleInfo.wheel.motorTorque = motor;
  116. }
  117. else if (axleInfo.motor)
  118. {
  119. axleInfo.wheel.motorTorque = 0;
  120. }
  121. }
  122. }
  123. }
  124. public void SetSpeed(float speed)
  125. {
  126. if (velocityMode == VelocityMode.Keyboard) return;
  127. currentSpeed = speed;
  128. }
  129. public void SetLeaningAngle(float angle)
  130. {
  131. if (velocityMode == VelocityMode.Keyboard) return;
  132. currentLeaningAngle = angle;
  133. }
  134. public void SetSteeringAngle(float angle)
  135. {
  136. if (velocityMode == VelocityMode.Keyboard) return;
  137. currentSteerAngle = angle;
  138. }
  139. //rotates the meshes
  140. void RotateObject(GameObject obj, float multiplier)
  141. {
  142. obj.transform.Rotate(Time.deltaTime * rb.velocity.magnitude * (360f / oneRotationSpeed) * multiplier, 0, 0);
  143. //obj.transform.Rotate(Time.deltaTime * rotSpeed * (360f / oneRotationSpeed) * multiplier, 0, 0);
  144. }
  145. public void SetTorque(float crankTorque)
  146. {
  147. foreach (AxleInfo axleInfo in axleInfos)
  148. {
  149. if (velocityMode == VelocityMode.ApplyTorqueToWheelCollider) ;
  150. {
  151. if (axleInfo.motor)
  152. {
  153. axleInfo.wheel.motorTorque = crankTorque;
  154. }
  155. }
  156. }
  157. }
  158. [System.Serializable]
  159. public class AxleInfo
  160. {
  161. public WheelCollider wheel;
  162. public bool motor; // is this wheel attached to motor?
  163. public bool steering; // does this wheel apply steer angle?
  164. }
  165. }