Untitled
custom car controlunknown
csharp
a year ago
6.0 kB
4
Indexable
Never
using System.Collections; using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class CustomCarPhysicControl : MonoBehaviour { private Rigidbody rb; [SerializeField] Transform []tires; [Header("Suspension")] [SerializeField] private float offset = 0.4f; [SerializeField] private float springForce = 100; [SerializeField] private float dampingForce = 10; [Header("Accleration")] [SerializeField] private float carTopSpeed = 10; [SerializeField] private AnimationCurve powerCurve; public float accelerationInput; [Header("Steering")] [SerializeField] private float tireMass = 2; [SerializeField] [Range(0, 1)] private float gripFactor = 0.4f; //[SerializeField] AnimationCurve gripFactor; [SerializeField] private float maxTurnTire = 45; public float currentTurn; private void Awake() { rb = GetComponent<Rigidbody>(); } private void Update() { Inputs(); WheelDisplay(); } private void FixedUpdate() { Acceleration(); Steering(); Suspension(); } void Inputs() { currentTurn += Input.GetAxis("Horizontal") * 0.5f; currentTurn = Mathf.Clamp(currentTurn, -maxTurnTire, maxTurnTire); accelerationInput = Input.GetAxis("Vertical"); } void Acceleration() { RaycastHit hit; for (int i = 0; i < tires.Length; i++) { if (Physics.Raycast(tires[i].position, Vector3.down, out hit, offset)) { //world-space direction of the acceleration/braking force. Vector3 accelerationDirection = tires[i].forward; //acceleration torgue if(accelerationInput > 0.0f) { //forwar speed of the car (in the firection of driving) float carSpeed = Vector3.Dot(transform.forward, rb.velocity); //normalized car speed float normalizedSpeed = Mathf.Clamp01(Mathf.Abs(carSpeed) / carTopSpeed); //available torque float availableTorque = powerCurve.Evaluate(normalizedSpeed) * accelerationInput; rb.AddForceAtPosition(accelerationDirection * availableTorque, tires[i].position); } } } } void Steering() { RaycastHit hit; for (int i = 0; i < tires.Length; i++) { if (Physics.Raycast(tires[i].position, Vector3.down, out hit, offset)) { //world space direction of the spring force. Vector3 steeringDirection = tires[i].right; //wold space velocity of this tire. Vector3 tireWorldVelocity = rb.GetPointVelocity(tires[i].position); //what it's the tire's velocit in the steering direction? //note that steeringDirection is a unit vector, so this returns thje magnitude of tireworldVelocity //as projected onto steeringDirection float steeringVelocity = Vector3.Dot(steeringDirection, tireWorldVelocity); //the change in velocity that we're looking for is -steeringVelocity * gripFactor //gripFactor is in range 0-1, 0 means NO grip, 1 means full grip float desiredVelocityChange = -steeringVelocity * gripFactor; //turn change in velocity into an acceleration (accleration = change in velocity / time ) //this will produce the acceleration necessary to change the velocity by desiredVelocityChange in 1 physics step float desiredAcceleration = desiredVelocityChange / Time.fixedDeltaTime; //Force = Mass * Acceleration, so multiply by the mass of the tire and as a force. rb.AddForceAtPosition(steeringDirection * tireMass * desiredAcceleration, tires[i].position); } } } void Suspension() { RaycastHit hit; for (int i = 0; i < tires.Length; i++) { if(Physics.Raycast(tires[i].position, Vector3.down, out hit, offset)) { //world space direction of the spring force. Vector3 springDirection = tires[i].up; //wold space velocity of this tire. Vector3 tireWorldVelocity = rb.GetPointVelocity(tires[i].position); //calculate offset from the raycast ( suspensionRestDist - tireRay.distance ) float raycastOffset = offset - hit.distance; //calculate velocity along the spring direction //note that springDir is a unit Vector, so this returns the magnitude of tireWorldVelocity float springVelocity = Vector3.Dot(springDirection, tireWorldVelocity); //calculate the magnitude of the dampened spring force. float force = (raycastOffset * springForce) - (springVelocity * dampingForce); //apply the force at the location of this tire, in the direction of suspension rb.AddForceAtPosition(springDirection * force, tires[i].position); } } } void WheelDisplay() { if (tires.Length > 0) { tires[0].transform.localRotation = Quaternion.Euler(0f, currentTurn, 0f); tires[1].transform.localRotation = Quaternion.Euler(0f, currentTurn, 0f); } } private void OnDrawGizmos() { if (tires.Length > 0) { for (int i = 0; i < tires.Length; i++) { Gizmos.DrawRay(tires[i].position, Vector3.down * offset); } } } }