using Code.DI; using Code.Input; using UnityEngine; namespace Code.Gameplay { [RequireComponent(typeof(Rigidbody))] public class CarController : MonoBehaviour { [Header("Physics")] [SerializeField] private float motorForce = 150000; [SerializeField] private float brakeForce = 300000; [SerializeField] private float maxSteerAngle = 25f; [SerializeField] private float turnSpeed = 50; [Header("Wheels")] [SerializeField] private Transform frontLeftWheel; [SerializeField] private Transform frontRightWheel; [Header("Camera")] [SerializeField] private Transform driverCameraPoint; [SerializeField] private Camera mainCamera; [SerializeField] private float thirdPersonDistance = 6f; [SerializeField] private float thirdPersonHeight = 2.5f; [SerializeField] private float cameraFollowSpeed = 4f; private Rigidbody _rb; private bool _isFirstPerson; private IInputService _inputService; private float _lastSwitchTime; private const float SwitchCooldown = 0.5f; private void Awake() { _rb = GetComponent(); } private void Start() { var container = FindFirstObjectByType(); _inputService = container.Resolve(); SwitchToThirdPerson(); } private void Update() { if (_inputService.SwitchCameraPressed) { if (Time.time - _lastSwitchTime >= SwitchCooldown) { _isFirstPerson = !_isFirstPerson; if (_isFirstPerson) SwitchToFirstPerson(); else SwitchToThirdPerson(); _lastSwitchTime = Time.time; } } } private void FixedUpdate() { var input = _inputService.MoveInput; var force = transform.forward * (input.y * motorForce); _rb.AddForce(force, ForceMode.Force); if (Mathf.Abs(input.y) < 0.1f && _rb.linearVelocity.magnitude > 0.3f) { _rb.AddForce(-_rb.linearVelocity * (brakeForce * Time.fixedDeltaTime), ForceMode.Force); } var steerInput = input.x; if (input.y < 0) steerInput = -input.x; var steer = steerInput * maxSteerAngle; if (frontLeftWheel) frontLeftWheel.localRotation = Quaternion.Euler(0, steer, 0); if (frontRightWheel) frontRightWheel.localRotation = Quaternion.Euler(0, steer, 0); if (!(_rb.linearVelocity.magnitude > 0.5f)) return; var turn = steerInput * turnSpeed * Time.fixedDeltaTime; _rb.MoveRotation(_rb.rotation * Quaternion.Euler(0, turn, 0)); } private void LateUpdate() { if (!mainCamera) return; if (_isFirstPerson) { if (driverCameraPoint) { mainCamera.transform.localPosition = driverCameraPoint.localPosition; mainCamera.transform.localRotation = driverCameraPoint.localRotation; } } else { mainCamera.transform.localPosition = new Vector3(0, 5, -8); mainCamera.transform.localRotation = Quaternion.Euler(20, 0, 0); } } private void SwitchToFirstPerson() { if (mainCamera) mainCamera.fieldOfView = 75; } private void SwitchToThirdPerson() { if (mainCamera) mainCamera.fieldOfView = 60; } } }