using UnityEngine; using UnityEngine.UI; using TMPro; public class RespawnCountdownUI : MonoBehaviour { [Header("Refs")] [SerializeField] private GameObject root; // DeathOverlayRoot [SerializeField] private TMP_Text titleText; // "DEAD" [SerializeField] private TMP_Text countdownText; [SerializeField] private Image radialFill; // Filled Image (Radial) [Header("Text")] [SerializeField] private string title = "DEAD"; [SerializeField] private string countdownFormat = "Respawn in {0}"; private bool _running; private double _endServerTime; private float _duration; private void Awake() { // 시작할 때는 UI 숨김 (root가 자신이 아닌 경우만) if (root != null && root != gameObject) { root.SetActive(false); } else if (root == gameObject) { // root가 자신인 경우, 자식인 Panel을 사용 Transform panelTransform = transform.Find("Panel"); if (panelTransform != null) { root = panelTransform.gameObject; root.SetActive(false); } } } // 외부에서 호출: 사망 시 UI 시작 public void Show(double respawnEndServerTime, float durationSeconds) { _endServerTime = respawnEndServerTime; _duration = Mathf.Max(0.01f, durationSeconds); titleText.text = title; root.SetActive(true); _running = true; // 초기값 SetVisual(remainingSeconds: (float)_duration); } // 외부에서 호출: 리스폰 완료 시 UI 종료 public void Hide() { _running = false; root.SetActive(false); } private void Update() { if (!_running) return; // 서버 기준 시간 사용 (Netcode 기준) // 만약 ServerTime이 없다면, "서버가 remainingSeconds를 주기적으로 보내는 방식"으로 대체 가능. double now = Unity.Netcode.NetworkManager.Singleton.ServerTime.Time; float remaining = (float)(_endServerTime - now); if (remaining <= 0f) { // 0초 도달: UI는 즉시 숨기거나, 리스폰 이벤트에서 Hide() 호출하도록 둘 중 택1 SetVisual(0f); return; } SetVisual(remaining); } private void SetVisual(float remainingSeconds) { int sec = Mathf.CeilToInt(Mathf.Max(0f, remainingSeconds)); countdownText.text = string.Format(countdownFormat, sec); // 1 -> 0으로 감소하는 연출 float t = Mathf.Clamp01(remainingSeconds / _duration); if (radialFill != null) radialFill.fillAmount = t; } }