Last active
August 12, 2021 21:03
-
-
Save nothke/bc3b6aee1aaa4f0825bc2908ce318913 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class CarTorque : MonoBehaviour | |
{ | |
//// Inspector | |
[Header("Geometry")] | |
public float wheelbase = 1; | |
public float trackWidth = 1; | |
[Header("Handling")] | |
// Turning to velocity multipliers: | |
public float sidewaysDragMult = 1; | |
public float yawDragMult = 1; | |
// Keep curves' y between 0-1 and use the multipliers for vertical scaling instead: | |
public float torqueVelocityMult = 1; | |
public AnimationCurve torqueByVelocityCurve = new AnimationCurve(new[] { new Keyframe(0, 0), new Keyframe(100, 1) }); | |
public float thrustVelocityMult = 1; | |
public AnimationCurve thrustByVelocityCurve = new AnimationCurve(new[] { new Keyframe(0, 1), new Keyframe(30, 0) }); | |
[Header("Suspension")] | |
public float springRate = 10; | |
public float damperRate = 1; // Optimal damper rate should always be ~1/10 of spring rate (not too stiff, not too bouncy). I don't know why exactly, it's the magic of the universe, it's true even in real cars :P | |
public float raycastDistance = 1; // ride height | |
//// private | |
Rigidbody _rb; | |
Rigidbody rb { get { if (!_rb) _rb = GetComponent<Rigidbody>(); return _rb; } } | |
Vector3[] wheelPoints; | |
private void Start() | |
{ | |
wheelPoints = new Vector3[4]; | |
wheelPoints[0] = new Vector3(-trackWidth * 0.5f, 0, wheelbase * 0.5f); // FL | |
wheelPoints[1] = new Vector3(trackWidth * 0.5f, 0, wheelbase * 0.5f); // FR | |
wheelPoints[2] = new Vector3(-trackWidth * 0.5f, 0, -wheelbase * 0.5f); // RL | |
wheelPoints[3] = new Vector3(trackWidth * 0.5f, 0, -wheelbase * 0.5f); // RR | |
} | |
private void FixedUpdate() | |
{ | |
bool grounded = false; | |
// Raycast from each wheel point, check grounding and push with suspension | |
for (int i = 0; i < wheelPoints.Length; i++) | |
{ | |
Vector3 wp = transform.TransformPoint(wheelPoints[i]); | |
if (Physics.Raycast(wp, -transform.up, out RaycastHit hit, raycastDistance)) | |
{ | |
grounded = true; | |
// Spring force is proportional to compression | |
float spring = (raycastDistance - hit.distance) * springRate; | |
// Damping force is proportional to vertical wheel velocity, clamped to prevent crazy values | |
Vector3 veloAtWheel = rb.GetPointVelocity(wp); | |
Vector3 relVeloAtWheel = transform.InverseTransformDirection(veloAtWheel); | |
float verticalRelVeloAtWheel = relVeloAtWheel.y; | |
float damp = -Mathf.Clamp(verticalRelVeloAtWheel, -2, 2) * damperRate; | |
rb.AddForceAtPosition(hit.normal * (spring + damp), wp); | |
} | |
} | |
if (grounded) | |
{ | |
var velo = rb.velocity; | |
var localVelo = transform.InverseTransformDirection(velo); | |
float sidewaysVelo = localVelo.x; | |
float forwardVelo = localVelo.z; | |
float torque = torqueByVelocityCurve.Evaluate(Mathf.Abs(sidewaysVelo)) * Mathf.Sign(sidewaysVelo) * torqueVelocityMult; | |
Vector3 localAngVelo = transform.InverseTransformDirection(rb.angularVelocity); | |
float yawRate = localAngVelo.y; | |
float yawDrag = -Mathf.Clamp(yawRate, -1, 1) * yawDragMult; | |
rb.AddRelativeTorque(0, torque + yawDrag, 0); | |
float thrust = thrustByVelocityCurve.Evaluate(Mathf.Clamp(forwardVelo, 0, Mathf.Infinity)) * forwardVelo * thrustVelocityMult; | |
rb.AddRelativeForce(-sidewaysVelo * sidewaysDragMult, 0, thrust); | |
} | |
} | |
// Draws lines for each wheel so you can set up wheelbase and track easily | |
private void OnDrawGizmosSelected() | |
{ | |
Vector3 fl = new Vector3(-trackWidth * 0.5f, 0, wheelbase * 0.5f); // FL | |
Vector3 fr = new Vector3(trackWidth * 0.5f, 0, wheelbase * 0.5f); // FR | |
Vector3 rl = new Vector3(-trackWidth * 0.5f, 0, -wheelbase * 0.5f); // RL | |
Vector3 rr = new Vector3(trackWidth * 0.5f, 0, -wheelbase * 0.5f); // RR | |
Gizmos.DrawRay(transform.TransformPoint(fl), -transform.up * raycastDistance); | |
Gizmos.DrawRay(transform.TransformPoint(fr), -transform.up * raycastDistance); | |
Gizmos.DrawRay(transform.TransformPoint(rl), -transform.up * raycastDistance); | |
Gizmos.DrawRay(transform.TransformPoint(rr), -transform.up * raycastDistance); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment