You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.5 KiB
C#
168 lines
5.5 KiB
C#
//----------------------------------------------
|
|
// Simple Car Controller
|
|
//
|
|
// Copyright © 2014 - 2023 BoneCracker Games
|
|
// http://www.bonecrackergames.com
|
|
//
|
|
//----------------------------------------------
|
|
|
|
using UnityEngine;
|
|
using System.Linq;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// Handling wheels. Visual and physicaly. Based on Unity's WheelCollider.
|
|
/// </summary>
|
|
[AddComponentMenu("BoneCracker Games/Simple Car Controller/SCC Wheel")]
|
|
[RequireComponent(typeof(WheelCollider))]
|
|
public class SCC_Wheel : MonoBehaviour {
|
|
|
|
// Rigidbody of the vehicle.
|
|
private Rigidbody rigid;
|
|
private Rigidbody Rigid {
|
|
|
|
get {
|
|
|
|
if (rigid == null)
|
|
rigid = GetComponentInParent<Rigidbody>();
|
|
|
|
return rigid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Drivetrain.
|
|
private SCC_Drivetrain drivetrain;
|
|
private SCC_Drivetrain Drivetrain {
|
|
|
|
get {
|
|
|
|
if (drivetrain == null)
|
|
drivetrain = GetComponentInParent<SCC_Drivetrain>();
|
|
|
|
return drivetrain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Wheelcollider.
|
|
private WheelCollider wheelCollider;
|
|
public WheelCollider WheelCollider {
|
|
|
|
get {
|
|
|
|
if (wheelCollider == null)
|
|
wheelCollider = GetComponent<WheelCollider>();
|
|
|
|
return wheelCollider;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
wheelCollider = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public Transform wheelModel; // Wheel model.
|
|
|
|
private float wheelRotation = 0f; // Current wheel rotation X axis
|
|
internal bool isGrounded = false; // Is this wheel grounded or not?
|
|
internal float totalSlip = 0f; // Total slipage.
|
|
internal float rpm = 0f; // Current rpm of the wheel.
|
|
internal float wheelRPMToSpeed = 0f; // RPM to speed converstaion.
|
|
|
|
private void Awake() {
|
|
|
|
// If wheel model is not selected, return.
|
|
if (!wheelModel) {
|
|
|
|
Debug.LogError(transform.name + " wheel of the " + Drivetrain.transform.name + " is missing wheel model. This wheel is disabled");
|
|
enabled = false;
|
|
return;
|
|
|
|
}
|
|
|
|
// Creating pivot point for the selected wheel model.
|
|
GameObject fixedModel = new GameObject(wheelModel.name);
|
|
fixedModel.transform.position = wheelModel.position;
|
|
fixedModel.transform.SetParent(Rigid.transform);
|
|
fixedModel.transform.localRotation = Quaternion.identity;
|
|
fixedModel.transform.localScale = Vector3.one;
|
|
|
|
foreach (Transform go in wheelModel.GetComponentsInChildren<Transform>())
|
|
go.SetParent(fixedModel.transform);
|
|
|
|
wheelModel = fixedModel.transform;
|
|
|
|
}
|
|
|
|
private void Update() {
|
|
|
|
// If there is no drivetrain or wheelcollider, return.
|
|
if (!Drivetrain || !WheelCollider) {
|
|
|
|
Debug.LogError("Drivetrain or wheelcollider is not found. This wheel is disabled");
|
|
enabled = false;
|
|
return;
|
|
|
|
}
|
|
|
|
WheelAlign();
|
|
|
|
}
|
|
|
|
private void FixedUpdate() {
|
|
|
|
WheelHit hit;
|
|
isGrounded = WheelCollider.GetGroundHit(out hit);
|
|
|
|
rpm = WheelCollider.rpm; // RPM of the wheel.
|
|
wheelRPMToSpeed = (((WheelCollider.rpm * WheelCollider.radius) / 2.8f) * Mathf.Lerp(1f, .75f, hit.forwardSlip)) * Rigid.transform.lossyScale.y; // RPM to speed.
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aligning wheel models.
|
|
/// </summary>
|
|
private void WheelAlign() {
|
|
|
|
if (!wheelModel) {
|
|
|
|
Debug.LogError(transform.name + " wheel of the " + Drivetrain.transform.name + " is missing wheel model. This wheel is disabled");
|
|
enabled = false;
|
|
return;
|
|
|
|
}
|
|
|
|
RaycastHit hit;
|
|
WheelHit CorrespondingGroundHit;
|
|
|
|
Vector3 ColliderCenterPoint = WheelCollider.transform.TransformPoint(WheelCollider.center);
|
|
WheelCollider.GetGroundHit(out CorrespondingGroundHit);
|
|
|
|
if (Physics.Raycast(ColliderCenterPoint, -WheelCollider.transform.up, out hit, (WheelCollider.suspensionDistance + WheelCollider.radius) * transform.localScale.y) && !hit.collider.isTrigger && !hit.transform.IsChildOf(Rigid.transform)) {
|
|
|
|
wheelModel.transform.position = hit.point + (WheelCollider.transform.up * WheelCollider.radius) * transform.localScale.y;
|
|
float extension = (-WheelCollider.transform.InverseTransformPoint(CorrespondingGroundHit.point).y - WheelCollider.radius) / WheelCollider.suspensionDistance;
|
|
Debug.DrawLine(CorrespondingGroundHit.point, CorrespondingGroundHit.point + WheelCollider.transform.up * (CorrespondingGroundHit.force / Rigid.mass), extension <= 0.0 ? Color.magenta : Color.white);
|
|
Debug.DrawLine(CorrespondingGroundHit.point, CorrespondingGroundHit.point - WheelCollider.transform.forward * CorrespondingGroundHit.forwardSlip * 2f, Color.green);
|
|
Debug.DrawLine(CorrespondingGroundHit.point, CorrespondingGroundHit.point - WheelCollider.transform.right * CorrespondingGroundHit.sidewaysSlip * 2f, Color.red);
|
|
|
|
} else {
|
|
|
|
wheelModel.transform.position = Vector3.Lerp(wheelModel.transform.position, ColliderCenterPoint - (WheelCollider.transform.up * WheelCollider.suspensionDistance) * transform.localScale.y, Time.deltaTime * 10f);
|
|
|
|
}
|
|
|
|
wheelRotation += WheelCollider.rpm * 6 * Time.deltaTime;
|
|
wheelModel.transform.rotation = WheelCollider.transform.rotation * Quaternion.Euler(wheelRotation, WheelCollider.steerAngle, WheelCollider.transform.rotation.z);
|
|
|
|
}
|
|
|
|
} |