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.")] [SerializeField] private 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); private Rigidbody targetRb; private float currentDistance; private Camera cam; private void Start() { Application.targetFrameRate = 120; cam = GetComponent(); currentDistance = baseDistance; if (target != null) { // User assigned a target in the Inspector InitializeTarget(); } else { // No target assigned, try to auto-find after a short delay Invoke(nameof(FindLocalPlayer), 0.5f); } } private void InitializeTarget() { targetRb = 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 FindLocalPlayer() { foreach (var vehicle in FindObjectsOfType()) { // VehicleController inherits NetworkBehaviour, so .Object is the NetworkObject if (vehicle.Object != null && vehicle.Object.HasInputAuthority) { target = vehicle.FollowTarget; InitializeTarget(); Debug.Log("CameraController: Auto-found local player to follow.", this); return; } } Debug.LogWarning("CameraController: No local player found to follow — disabling.", this); enabled = false; } private void LateUpdate() { if (target == null || targetRb == null) return; 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); } }