Perekyp/Assets/Scripts/Car/CarController.cs

112 lines
4.1 KiB
C#

using UnityEngine;
public enum DriveType { FWD, RWD, AWD } // Передний, Задний, Полный привод
[RequireComponent(typeof(Rigidbody))]
public class CarController : MonoBehaviour
{
[Header("Drive Settings")]
public DriveType driveType = DriveType.AWD;
[SerializeField] private float motorForce = 1500f;
[SerializeField] private float brakeForce = 3000f;
[SerializeField] private float maxSteerAngle = 30f;
[Header("Arcade Feel")]
[SerializeField] private Transform centerOfMass; // Заниженный центр тяжести
[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;
private Rigidbody rb;
private float currentMotorForce;
private float currentBrakeForce;
private float currentSteerAngle;
private void Start()
{
rb = GetComponent<Rigidbody>();
if (centerOfMass != null)
{
rb.centerOfMass = centerOfMass.localPosition; // Смещаем центр масс вниз для аркадности
}
}
// Метод вызывается из другого скрипта (ввода)
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();
}
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()
{
frontLeftCollider.brakeTorque = currentBrakeForce;
frontRightCollider.brakeTorque = currentBrakeForce;
rearLeftCollider.brakeTorque = currentBrakeForce;
rearRightCollider.brakeTorque = currentBrakeForce;
}
private void UpdateWheelPoses()
{
UpdateWheelPose(frontLeftCollider, frontLeftMesh);
UpdateWheelPose(frontRightCollider, frontRightMesh);
UpdateWheelPose(rearLeftCollider, rearLeftMesh);
UpdateWheelPose(rearRightCollider, rearRightMesh);
}
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;
}
}