BicycleController.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. GUI.TextField(new Rect(114, 10, 304, 20), $"Wanted speed {(currentSpeed * 3.6):n2} km/h; Current Speed {(rb.velocity.magnitude *3.6):n2} km/h");
  54. }
  55. // Update is called once per frame
  56. void Update()
  57. {
  58. if (velocityMode == VelocityMode.Keyboard)
  59. {
  60. currentSpeed = Input.GetAxis("Vertical") * 8.3333f;
  61. currentSteerAngle = Input.GetAxis("Horizontal") * maxSteeringAngle;
  62. }
  63. RotateMeshes();
  64. //RotateFork();
  65. Debug.Log("rotation: " + currentSteerAngle);
  66. }
  67. public void FixedUpdate()
  68. {
  69. ApplyWheelForce();
  70. Lean();
  71. //RotateStraight();
  72. }
  73. void RotateMeshes()
  74. {
  75. //RotateObject(crank, 1);
  76. //RotateObject(pedalL, -1);
  77. //RotateObject(pedalR, -1);
  78. RotateObject(rearWheel, crankMultiplier);
  79. RotateObject(frontWheel, crankMultiplier);
  80. }
  81. void RotateFork()
  82. {
  83. fork.transform.localRotation = startForkRot;
  84. fork.transform.RotateAround(fork.transform.position, fork.transform.up, maxSteeringAngle * currentSteerAngle);
  85. }
  86. void Lean()
  87. {
  88. upDirection = Vector3.Normalize(Vector3.up + transform.right *
  89. (maxSteeringAngle * relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude) / 100);
  90. }
  91. void ApplyWheelForce()
  92. {
  93. float motor = maxMotorTorque;
  94. float steering = maxSteeringAngle * currentSteerAngle;
  95. leftWheels.localPosition = -Vector3.up * (relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude);
  96. rightWheels.localPosition = Vector3.up * (relativeLeanAmount * currentSteerAngle * rb.velocity.magnitude);
  97. if (velocityMode == VelocityMode.ApplySpeedToRigidBody)
  98. {
  99. //TODO: figure out what to do when going upwards?
  100. rb.velocity = bike.transform.forward * currentSpeed;
  101. }
  102. foreach (AxleInfo axleInfo in axleInfos)
  103. {
  104. if (axleInfo.steering)
  105. {
  106. axleInfo.wheel.steerAngle = steering;
  107. }
  108. if (velocityMode == VelocityMode.ApplySpeedToWheelCollider || velocityMode == VelocityMode.Keyboard)
  109. {
  110. if (axleInfo.motor && rb.velocity.magnitude < currentSpeed)
  111. {
  112. axleInfo.wheel.motorTorque = motor;
  113. rb.drag = 0.01f;
  114. }
  115. else if (axleInfo.motor && rb.velocity.magnitude > 5)
  116. {
  117. rb.drag = 100f;
  118. axleInfo.wheel.motorTorque = 0;
  119. }
  120. }
  121. }
  122. }
  123. public void SetSpeed(float speed)
  124. {
  125. if (velocityMode == VelocityMode.Keyboard) return;
  126. currentSpeed = speed;
  127. }
  128. public void SetLeaningAngle(float angle)
  129. {
  130. if (velocityMode == VelocityMode.Keyboard) return;
  131. currentLeaningAngle = angle;
  132. }
  133. public void SetSteeringAngle(float angle)
  134. {
  135. if (velocityMode == VelocityMode.Keyboard) return;
  136. currentSteerAngle = angle;
  137. }
  138. //rotates the meshes
  139. void RotateObject(GameObject obj, float multiplier)
  140. {
  141. obj.transform.Rotate(Time.deltaTime * rb.velocity.magnitude * (360f / oneRotationSpeed) * multiplier, 0, 0);
  142. //obj.transform.Rotate(Time.deltaTime * rotSpeed * (360f / oneRotationSpeed) * multiplier, 0, 0);
  143. }
  144. public void SetTorque(float crankTorque)
  145. {
  146. foreach (AxleInfo axleInfo in axleInfos)
  147. {
  148. if (velocityMode == VelocityMode.ApplyTorqueToWheelCollider) ;
  149. {
  150. if (axleInfo.motor)
  151. {
  152. axleInfo.wheel.motorTorque = crankTorque;
  153. }
  154. }
  155. }
  156. }
  157. [System.Serializable]
  158. public class AxleInfo
  159. {
  160. public WheelCollider wheel;
  161. public bool motor; // is this wheel attached to motor?
  162. public bool steering; // does this wheel apply steer angle?
  163. }
  164. }