using System.Collections; using UnityEngine; public class CameraController : MonoBehaviour { [Header("Follow")] public Transform target; public Vector3 followOffset = new Vector3(0f, 1.7f, -3.5f); public float followSmooth = 10f; public float rotationSmooth = 12f; [Header("Fixed Camera")] public float transitionTime = 1.1f; public DepthOfFieldController depthOfFieldController; public bool IsInFixedMode { get; private set; } private float pitch; private Coroutine fixedCameraRoutine; private void Start() { SnapToFollowPosition(); } private void LateUpdate() { if (IsInFixedMode || target == null) { return; } // Normal mode: keep the rig behind the player and match the player's yaw plus camera pitch. Vector3 desiredPosition = GetFollowPosition(); Quaternion desiredRotation = GetFollowRotation(); transform.position = Vector3.Lerp(transform.position, desiredPosition, followSmooth * Time.deltaTime); transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, rotationSmooth * Time.deltaTime); } public void SetPitch(float newPitch) { pitch = newPitch; } public void SetFixedCamera(Transform point, float duration) { if (point == null) { return; } if (fixedCameraRoutine != null) { StopCoroutine(fixedCameraRoutine); } fixedCameraRoutine = StartCoroutine(FixedCameraRoutine(point, duration)); } private IEnumerator FixedCameraRoutine(Transform point, float duration) { IsInFixedMode = true; depthOfFieldController?.EnableFocus(point); // Attention mode: move to the authored point, hold the shot, then return control to the player. yield return MoveCamera(transform.position, transform.rotation, point.position, point.rotation, transitionTime); yield return new WaitForSeconds(duration); yield return MoveCamera(transform.position, transform.rotation, GetFollowPosition(), GetFollowRotation(), transitionTime); depthOfFieldController?.DisableFocus(); IsInFixedMode = false; fixedCameraRoutine = null; } private IEnumerator MoveCamera(Vector3 startPosition, Quaternion startRotation, Vector3 endPosition, Quaternion endRotation, float time) { float timer = 0f; while (timer < time) { timer += Time.deltaTime; float t = Mathf.Clamp01(timer / time); transform.position = Vector3.Lerp(startPosition, endPosition, t); transform.rotation = Quaternion.Slerp(startRotation, endRotation, t); yield return null; } transform.position = endPosition; transform.rotation = endRotation; } private Vector3 GetFollowPosition() { if (target == null) { return transform.position; } Quaternion yawRotation = Quaternion.Euler(0f, target.eulerAngles.y, 0f); return target.position + yawRotation * followOffset; } private Quaternion GetFollowRotation() { if (target == null) { return transform.rotation; } return Quaternion.Euler(pitch, target.eulerAngles.y, 0f); } private void SnapToFollowPosition() { if (target == null) { return; } transform.position = GetFollowPosition(); transform.rotation = GetFollowRotation(); } }