using UnityEngine; using UnityEngine.UIElements; // UI Toolkit 버전 대사 HUD. DialogUI.uxml의 요소(#SpeakerName / #DialogText / #DialogField)를 잡아 // 화자 이름 + 대사를 표시한다. // 공개 API(Instance / Show / Hide)는 기존과 동일 — DialogPlayer는 수정 없이 그대로 쓴다. // // UIDocument의 후속인 PanelRenderer를 쓴다. 요소 참조는 UI 리로드 콜백으로 받는다: // - rootVisualElement가 준비됐는지 매번 확인하던 지연 초기화(EnsureRefs)가 사라진다. // - 플레이 중 UXML을 수정해 UI가 리로드돼도 참조가 자동으로 다시 연결된다. [RequireComponent(typeof(PanelRenderer))] public class DialogHud : MonoBehaviour { public static DialogHud Instance { get; private set; } private PanelRenderer _panelRenderer; private VisualElement _panel; // 대사 패널(#DialogField) — 토글 대상 private Label _speakerName; private Label _dialogText; // 현재 표시 상태. 리로드로 요소가 새로 만들어졌을 때 이 값으로 복원한다. private bool _visible; private string _speakerText = string.Empty; private string _bodyText = string.Empty; // 같은 버전으로 콜백이 중복 호출될 때 헛일을 막는다 (Unity 권장 패턴) private int _uiVersion = -1; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; _panelRenderer = GetComponent(); // root가 이미 준비돼 있으면 즉시 호출되고, 이후 UI가 리로드될 때마다 다시 호출된다 _panelRenderer.RegisterUIReloadCallback(OnUIReload); } private void OnDestroy() { if (_panelRenderer != null) _panelRenderer.UnregisterUIReloadCallback(OnUIReload); if (Instance == this) Instance = null; } // UI가 (재)구성될 때마다 요소를 다시 잡고 현재 표시 상태를 그대로 되돌린다. private void OnUIReload(PanelRenderer panelRenderer, VisualElement root, int version) { if (_uiVersion == version) return; _uiVersion = version; _panel = root.Q("DialogField"); _speakerName = root.Q