using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class CarController : MonoBehaviour
{
private const string HORIZONTAL = “Horizontal”;
private const string VERTICAL = “Vertical”;
private float horizontalInput;
private float verticalInput;
private float currentSteerAngle;
private float currentBreakForce;
private bool isBreaking;
private WheelFrictionCurve defaultFrontWFC;
private WheelFrictionCurve defaultRearWFC;
private void Start()
{
defaultFrontWFC = frontRightWheelCol.sidewaysFriction;
defaultRearWFC = rearRightWheelCol.sidewaysFriction;
}
private void Update()
{
if (Input.GetKey(KeyCode.LeftShift) || Input.GetButton(“Shift”))
ApplyDrifting();
else if (frontRightWheelCol.sidewaysFriction.extremumSlip != defaultFrontWFC.extremumSlip && !Input.GetKey(KeyCode.LeftShift))
ResetWheelSettings();
}
private void FixedUpdate()
{
GetInput();
HandleMotor();
HandleSteering();
UpdateWheels();
}
/// <summary>
/// Get the input for turning, forward or backwards and breaking.
/// </summary>
private void GetInput()
{
horizontalInput = Input.GetAxis(HORIZONTAL);
verticalInput = Input.GetAxis(VERTICAL);
isBreaking = Input.GetKey(KeyCode.Space);
}
#region Car settings
[Header(“Car Settings”)]
[SerializeField] private float motorForce;
[SerializeField] private float breakForce;
[SerializeField] private float maxSteerAngle;
[Header(“Drift Settings”)]
[SerializeField] private float driftForce;
[Space(10)]
[SerializeField] private bool twoWheelDrive;
[SerializeField] private bool fourWheelDrive;
[Header(“Wheel Colliders”)]
[SerializeField] private WheelCollider frontLeftWheelCol;
[SerializeField] private WheelCollider frontRightWheelCol;
[SerializeField] private WheelCollider rearLeftWheelCol;
[SerializeField] private WheelCollider rearRightWheelCol;
[Header(“Wheel Transforms”)]
[SerializeField] private Transform frontLeftWheelTransform;
[SerializeField] private Transform frontRightWheelTransform;
[SerializeField] private Transform rearLeftWheelTransform;
[SerializeField] private Transform rearRightWheelTransform;
#endregion
#region Car/Wheel behaviour
/// <summary>
/// Gives the wheels power depending on Vertical Input and sets breakforce when u break.
/// </summary>
private void HandleMotor()
{
if (!twoWheelDrive && !fourWheelDrive)
{
Debug.LogWarning(“Both Wheel drive options are off so the car can’t drive”);
return;
}
else if(twoWheelDrive && !fourWheelDrive)
{
frontLeftWheelCol.motorTorque = verticalInput * motorForce;
frontRightWheelCol.motorTorque = verticalInput * motorForce;
}
else if (fourWheelDrive)
{
frontLeftWheelCol.motorTorque = verticalInput * motorForce;
frontRightWheelCol.motorTorque = verticalInput * motorForce;
rearLeftWheelCol.motorTorque = verticalInput * motorForce;
rearRightWheelCol.motorTorque = verticalInput * motorForce;
}
currentBreakForce = isBreaking ? breakForce : 0f;
ApplyBreaking();
}
/// <summary>
/// Set the Brake Torque as the breakforce.
/// </summary>
private void ApplyBreaking()
{
frontRightWheelCol.brakeTorque = currentBreakForce;
frontLeftWheelCol.brakeTorque = currentBreakForce;
rearLeftWheelCol.brakeTorque = currentBreakForce;
rearRightWheelCol.brakeTorque = currentBreakForce;
}
/// <summary>
/// Changes the extremumslip in sideways friction to create drift effect.
/// </summary>
private void ApplyDrifting()
{
WheelFrictionCurve frontWfc = frontRightWheelCol.sidewaysFriction;
frontWfc.extremumSlip = driftForce;
WheelFrictionCurve rearWfc = rearRightWheelCol.sidewaysFriction;
rearWfc.extremumSlip = driftForce;
frontRightWheelCol.sidewaysFriction = frontWfc;
frontLeftWheelCol.sidewaysFriction = frontWfc;
rearLeftWheelCol.sidewaysFriction = rearWfc;
rearRightWheelCol.sidewaysFriction = rearWfc;
}
/// <summary>
/// Resets the sideways friction settings to normal after drifting.
/// </summary>
private void ResetWheelSettings()
{
frontRightWheelCol.sidewaysFriction = defaultFrontWFC;
frontLeftWheelCol.sidewaysFriction = defaultFrontWFC;
rearRightWheelCol.sidewaysFriction = defaultRearWFC;
rearLeftWheelCol.sidewaysFriction = defaultRearWFC;
}
/// <summary>
/// Calculates the angle depending on the Horizontal Input and turns the front wheels.
/// </summary>
private void HandleSteering()
{
currentSteerAngle = maxSteerAngle * horizontalInput;
frontLeftWheelCol.steerAngle = currentSteerAngle;
frontRightWheelCol.steerAngle = currentSteerAngle;
}
//Update all wheels.
private void UpdateWheels()
{
UpdateSingleWheel(frontLeftWheelTransform, frontLeftWheelCol);
UpdateSingleWheel(frontRightWheelTransform, frontRightWheelCol);
UpdateSingleWheel(rearLeftWheelTransform, rearLeftWheelCol);
UpdateSingleWheel(rearRightWheelTransform, rearRightWheelCol);
}
/// <summary>
/// Set the wheel position and rotation the same as the Wheel Collider.
/// </summary>
/// <param name=”wheelTransform”>The Wheel u want to turn.</param>
/// <param name=”wheelCollider”>The Wheel Collider the wheel copies. (Should be the same as the transform wheel. </param>
private void UpdateSingleWheel(Transform wheelTransform, WheelCollider wheelCollider)
{
Vector3 pos;
Quaternion rot;
wheelCollider.GetWorldPose(out pos, out rot);
wheelTransform.rotation = rot;
wheelTransform.position = pos;
}
#endregion
}