using UnityEngine; using RaceFields.Vehicles; namespace RaceFields.CameraSystem { [DisallowMultipleComponent] public sealed class BuggyFollowCamera : MonoBehaviour { [SerializeField] private Transform target; [SerializeField] private Vector3 followOffset = new Vector3(0f, 3.2f, -6.2f); [SerializeField] private Vector3 lookOffset = new Vector3(0f, 1.1f, 1.2f); [SerializeField] private float positionSmoothTime = 0.12f; [SerializeField] private float rotationLerp = 12f; [SerializeField] private bool autoFindTarget = true; [SerializeField] private float targetSearchInterval = 0.25f; private Vector3 velocity; private float nextTargetSearchTime; private void Start() { ResolveTarget(); SnapToTarget(); } private void LateUpdate() { ResolveTarget(); if (target == null) return; Vector3 desiredPosition = target.TransformPoint(followOffset); transform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref velocity, positionSmoothTime); Vector3 lookPoint = target.TransformPoint(lookOffset); Quaternion desiredRotation = Quaternion.LookRotation(lookPoint - transform.position, Vector3.up); transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, rotationLerp * Time.deltaTime); } [ContextMenu("Snap To Target")] public void SnapToTarget() { ResolveTarget(); if (target == null) return; transform.position = target.TransformPoint(followOffset); transform.LookAt(target.TransformPoint(lookOffset), Vector3.up); velocity = Vector3.zero; } public void SetTarget(Transform newTarget, bool snap) { target = newTarget; velocity = Vector3.zero; if (snap) SnapToTarget(); } private void ResolveTarget() { if (target != null || !autoFindTarget) return; if (Time.unscaledTime < nextTargetSearchTime) return; nextTargetSearchTime = Time.unscaledTime + targetSearchInterval; ArcadeBuggyController controller = Object.FindFirstObjectByType(); if (controller != null) target = controller.transform; } } }