Projext/Assets/02_Scripts/Camera/CinemachineAutoTarget.cs

91 lines
4.9 KiB
C#
Raw Normal View History

using UnityEngine; // 임포트할거에요 -> Unity 엔진 기본 기능을
using Cinemachine; // 임포트할거에요 -> Cinemachine 카메라 시스템을
// ══════════════════════════════════════════════════════════════════════
// CinemachineAutoTarget — 씬 로드 시 플레이어 자동 추적
//
// DontDestroyOnLoad로 플레이어가 씬을 넘어올 때,
// 새 씬의 Cinemachine 카메라가 자동으로 플레이어를 찾아 Follow/LookAt 설정
//
// 사용법: 보스 씬(또는 모든 씬)의 CinemachineVirtualCamera 오브젝트에 부착
// playerTag에 플레이어 오브젝트의 태그를 설정 (기본: "Player")
// ══════════════════════════════════════════════════════════════════════
public class CinemachineAutoTarget : MonoBehaviour // 클래스를 정의할거에요 -> 카메라 자동 타겟 연결기를
{
[Header("플레이어 탐색 설정")]
[Tooltip("플레이어 오브젝트의 태그 (기본: Player)")]
[SerializeField] private string playerTag = "Player"; // 변수를 선언할거에요 -> 플레이어 태그를
[Tooltip("Follow와 LookAt 둘 다 설정할지 여부")]
[SerializeField] private bool setLookAt = true; // 변수를 선언할거에요 -> LookAt도 설정할지 여부를
[Tooltip("플레이어 탐색 재시도 간격 (초)")]
[SerializeField] private float retryInterval = 0.5f; // 변수를 선언할거에요 -> 재시도 간격을
[Tooltip("최대 탐색 시간 (초) — 이 시간 안에 못 찾으면 포기")]
[SerializeField] private float maxSearchTime = 10f; // 변수를 선언할거에요 -> 최대 탐색 시간을
private CinemachineVirtualCamera _vCam; // 변수를 선언할거에요 -> 가상 카메라 캐시를
private void Awake() // 초기화 시 실행할거에요 -> 카메라 캐싱을
{
_vCam = GetComponent<CinemachineVirtualCamera>(); // 캐싱할거에요 -> VirtualCamera 컴포넌트를
}
private void Start() // 시작 시 실행할거에요 -> 플레이어 탐색을
{
if (_vCam == null) return; // 방어할거에요 -> 카메라가 없으면
// 이미 Follow가 설정되어 있고 유효하면 스킵
if (_vCam.Follow != null) // 조건이 맞으면 실행할거에요 -> 이미 타겟이 있으면
{
Debug.Log("[CinemachineAutoTarget] Follow 타겟이 이미 설정되어 있음 — 스킵"); // 로그를 찍을거에요
return; // 중단할거에요
}
// 플레이어 즉시 탐색 시도
if (!TryFindAndAssignPlayer()) // 조건이 맞으면 실행할거에요 -> 즉시 못 찾으면
{
StartCoroutine(SearchPlayerCoroutine()); // 코루틴 시작할거에요 -> 반복 탐색을
}
}
/// <summary>
/// 플레이어를 찾아서 카메라에 연결 시도. 성공하면 true 반환.
/// </summary>
private bool TryFindAndAssignPlayer() // 함수를 정의할거에요 -> 플레이어 탐색 + 연결을
{
GameObject player = GameObject.FindGameObjectWithTag(playerTag); // 찾을거에요 -> 플레이어 태그를 가진 오브젝트를
if (player == null) return false; // 못 찾으면 false 반환
_vCam.Follow = player.transform; // 설정할거에요 -> Follow 타겟을 플레이어로
if (setLookAt) // 조건이 맞으면 실행할거에요 -> LookAt도 설정하라고 했으면
_vCam.LookAt = player.transform; // 설정할거에요 -> LookAt 타겟을 플레이어로
Debug.Log($"[CinemachineAutoTarget] 플레이어 자동 연결 완료: {player.name}"); // 로그를 찍을거에요
return true; // 성공 반환
}
/// <summary>
/// 플레이어가 아직 로드 안 됐을 수 있으니 일정 간격으로 재탐색
/// (DontDestroyOnLoad 플레이어가 씬 전환 후 약간 늦게 활성화될 수 있음)
/// </summary>
private System.Collections.IEnumerator SearchPlayerCoroutine() // 코루틴을 정의할거에요 -> 반복 탐색을
{
float elapsed = 0f; // 초기화할거에요 -> 경과 시간을
while (elapsed < maxSearchTime) // 반복할거에요 -> 최대 시간까지
{
yield return new WaitForSeconds(retryInterval); // 대기할거에요 -> 재시도 간격만큼
elapsed += retryInterval; // 더할거에요 -> 경과 시간에
if (TryFindAndAssignPlayer()) // 조건이 맞으면 실행할거에요 -> 찾았으면
yield break; // 코루틴 종료
}
Debug.LogWarning("[CinemachineAutoTarget] 플레이어를 찾지 못했습니다! 태그를 확인해주세요."); // 경고 로그
}
}