using UnityEngine; [RequireComponent(typeof(Camera))] public class CameraController : MonoBehaviour { [Header("Target")] [Tooltip("If set, camera will follow this Transform. Otherwise it will auto-find the local player.")] public Transform target; [Header("Zoom Settings")] [SerializeField] private float baseDistance = 6f; [SerializeField] private float maxDistance = 12f; [SerializeField] private float zoomSpeed = 5f; [Header("Follow Settings")] [SerializeField] private float followSmoothness = 5f; [SerializeField] private Vector3 heightOffset = new Vector3(0, 3f, 0); [Header("FOV Boost Settings")] [SerializeField] private float baseFOV = 60f; [SerializeField] private float boostFOV = 75f; [SerializeField] private float fovLerpSpeed = 5f; private float currentDistance; private Rigidbody targetRb; private Camera cam; private MotionBlur motionBlur; private bool isBoosting = false; private void Awake() { motionBlur = GetComponent(); cam = GetComponent(); } private void Start() { Application.targetFrameRate = 120; currentDistance = baseDistance; if (target != null) { InitializeTarget(); } transform.parent = null; } public void InitializeTarget() { targetRb = target.GetComponent(); motionBlur.vehicle = target.GetComponent(); if (targetRb == null) { Debug.LogError("CameraController: Assigned target has no Rigidbody component.", this); enabled = false; return; } Debug.Log("CameraController: Following manually assigned target.", this); } private void LateUpdate() { if (target == null || targetRb == null) return; // Dynamic zoom distance based on speed float speed = targetRb.velocity.magnitude; float targetDistance = Mathf.Lerp(baseDistance, maxDistance, speed / 30f); currentDistance = Mathf.Lerp(currentDistance, targetDistance, Time.deltaTime * zoomSpeed); Vector3 followPos = target.position + heightOffset - target.forward * currentDistance; transform.position = Vector3.Lerp(transform.position, followPos, Time.deltaTime * followSmoothness); transform.LookAt(target.position + heightOffset * 0.5f); // FOV Kick Logic float targetFOV = isBoosting ? boostFOV : baseFOV; cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, targetFOV, Time.deltaTime * fovLerpSpeed); } public void SetBoosting(bool boosting) { isBoosting = boosting; } }