Untitled
custom car controlunknown
csharp
3 years ago
6.0 kB
14
Indexable
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);
}
}
}
}
Editor is loading...