Perekyp/Assets/Scripts/Car/CarController.cs

129 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
public enum DriveType { FWD, RWD, AWD } // Передний, Задний, Полный привод
[RequireComponent(typeof(Rigidbody))]
public class CarController : MonoBehaviour
{
public float SpeedKmH => rb.linearVelocity.magnitude * 3.6f;
[Header("Drive Settings")]
public DriveType driveType = DriveType.AWD;
[SerializeField] private float motorForce = 1500f;
[SerializeField] private float brakeForce = 3000f;
[SerializeField] private float maxSteerAngle = 30f;
[Header("Wheel Colliders")]
[SerializeField] private WheelCollider frontLeftCollider;
[SerializeField] private WheelCollider frontRightCollider;
[SerializeField] private WheelCollider rearLeftCollider;
[SerializeField] private WheelCollider rearRightCollider;
[Header("Wheel Meshes (для визуализации)")]
[SerializeField] private Transform frontLeftMesh;
[SerializeField] private Transform frontRightMesh;
[SerializeField] private Transform rearLeftMesh;
[SerializeField] private Transform rearRightMesh;
[Header("Arcade Braking")]
[SerializeField] private float brakingDrag = 2f;
private float defaultDrag;
private Rigidbody rb;
private float currentMotorForce;
private float currentBrakeForce;
private float currentSteerAngle;
private void Start()
{
rb = GetComponent<Rigidbody>();
defaultDrag = rb.linearDamping;
}
// Метод вызывается из другого скрипта (ввода)
public void ProcessInput(float verticalInput, float horizontalInput, bool isBraking)
{
currentSteerAngle = maxSteerAngle * horizontalInput;
currentMotorForce = verticalInput * motorForce;
currentBrakeForce = isBraking ? brakeForce : 0f;
}
private void FixedUpdate()
{
HandleMotor();
HandleSteering();
ApplyBraking();
UpdateWheelPoses();
ApplyArcadeDrag();
}
private void HandleMotor()
{
// Распределяем крутящий момент в зависимости от типа привода
switch (driveType)
{
case DriveType.FWD: // Передний (недостаточная поворачиваемость, стабилен)
frontLeftCollider.motorTorque = currentMotorForce;
frontRightCollider.motorTorque = currentMotorForce;
break;
case DriveType.RWD: // Задний (склонен к заносам / дрифту)
rearLeftCollider.motorTorque = currentMotorForce;
rearRightCollider.motorTorque = currentMotorForce;
break;
case DriveType.AWD: // Полный (отличный старт и сцепление)
float halfForce = currentMotorForce / 2f;
frontLeftCollider.motorTorque = halfForce;
frontRightCollider.motorTorque = halfForce;
rearLeftCollider.motorTorque = halfForce;
rearRightCollider.motorTorque = halfForce;
break;
}
}
private void HandleSteering()
{
frontLeftCollider.steerAngle = currentSteerAngle;
frontRightCollider.steerAngle = currentSteerAngle;
}
private void ApplyBraking()
{
float frontBrake = currentBrakeForce;
float rearBrake = currentBrakeForce * 0.4f;
frontLeftCollider.brakeTorque = frontBrake;
frontRightCollider.brakeTorque = frontBrake;
rearLeftCollider.brakeTorque = rearBrake;
rearRightCollider.brakeTorque = rearBrake;
}
private void UpdateWheelPoses()
{
UpdateWheelPose(frontLeftCollider, frontLeftMesh);
UpdateWheelPose(frontRightCollider, frontRightMesh);
UpdateWheelPose(rearLeftCollider, rearLeftMesh);
UpdateWheelPose(rearRightCollider, rearRightMesh);
}
private void ApplyArcadeDrag()
{
// Если нажали тормоз и машина едет быстрее 1 м/с
if (currentBrakeForce > 0 && rb.linearVelocity.magnitude > 1f)
{
rb.linearDamping = brakingDrag;
}
else
{
rb.linearDamping = defaultDrag;
}
}
private void UpdateWheelPose(WheelCollider collider, Transform mesh)
{
if (mesh == null) return;
collider.GetWorldPose(out Vector3 pos, out Quaternion rot);
mesh.position = pos;
mesh.rotation = rot;
}
}