using UnityEngine; using UnityEngine.SceneManagement; using System.Collections; using TMPro; // ========================================== // ✨ [중요] 이 위치에 있어야 에러가 나지 않습니다. // ========================================== [System.Serializable] public struct TipLayoutSettings { public string label; [Header("TipBar (배경 막대) 설정")] public Vector3 barPosition; public float barWidth; public float barHeight; [Header("TipText (텍스트 영역) 설정")] public Vector3 textPosition; public float textWidth; public float textHeight; } public class SceneLoader : MonoBehaviour { public static SceneLoader Instance; [Header("로딩 UI 연결 (자식 오브젝트 권장)")] public GameObject loadingCanvas; public CanvasGroup mainGroup; [Header("로딩 시 나타날 요소들")] public TextMeshProUGUI tipText; public GameObject loadingTextObject; public GameObject tipBarObject; public RectTransform tipBarBackgroundRect; [Header("설정")] public string[] tips; public float fadeDuration = 0.8f; [Header("줄 수에 따른 수동 레이아웃")] public TipLayoutSettings[] manualLayouts; // 이제 여기서 에러가 나지 않습니다. private RectTransform _tipBarRect; private RectTransform _tipTextRect; private bool _isFading = false; private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); return; } if (loadingCanvas != null) loadingCanvas.SetActive(false); if (tipText != null) _tipTextRect = tipText.GetComponent(); _tipBarRect = tipBarBackgroundRect != null ? tipBarBackgroundRect : tipBarObject?.GetComponent(); if (mainGroup != null) mainGroup.alpha = 0f; } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (loadingCanvas != null && loadingCanvas.activeSelf) { StopAllCoroutines(); StartCoroutine(FadeOutAfterLoad()); } } public void LoadSceneWithFade(string sceneName) { if (_isFading) return; StartCoroutine(LoadProcess(sceneName)); } private IEnumerator LoadProcess(string sceneName) { _isFading = true; SetupTipText(); yield return null; ApplyManualLayout(); if (loadingCanvas != null) loadingCanvas.SetActive(true); yield return StartCoroutine(Fade(1f, mainGroup)); AsyncOperation op = SceneManager.LoadSceneAsync(sceneName); op.allowSceneActivation = false; float timer = 0f; while (timer < 2.0f || op.progress < 0.9f) { timer += Time.deltaTime; yield return null; } op.allowSceneActivation = true; } private IEnumerator FadeOutAfterLoad() { yield return StartCoroutine(Fade(0f, mainGroup)); if (loadingCanvas != null) loadingCanvas.SetActive(false); _isFading = false; } private void SetupTipText() { if (tipText == null) return; if (tips != null && tips.Length > 0) tipText.text = $"Tip! : {tips[Random.Range(0, tips.Length)]}"; else tipText.text = ""; } private void ApplyManualLayout() { if (tipText == null || _tipBarRect == null || _tipTextRect == null) return; if (string.IsNullOrWhiteSpace(tipText.text)) { if (tipBarObject != null) tipBarObject.SetActive(false); return; } if (tipBarObject != null) tipBarObject.SetActive(true); tipText.ForceMeshUpdate(true); int lineCount = tipText.textInfo.lineCount; int layoutIndex = Mathf.Clamp(lineCount - 1, 0, manualLayouts.Length - 1); if (manualLayouts.Length > 0) { TipLayoutSettings settings = manualLayouts[layoutIndex]; _tipBarRect.anchoredPosition = settings.barPosition; _tipBarRect.sizeDelta = new Vector2(settings.barWidth, settings.barHeight); _tipTextRect.anchoredPosition = settings.textPosition; _tipTextRect.sizeDelta = new Vector2(settings.textWidth, settings.textHeight); } } private IEnumerator Fade(float targetAlpha, CanvasGroup canvasGroup) { if (canvasGroup == null) yield break; float speed = 1f / Mathf.Max(0.01f, fadeDuration); while (canvasGroup != null && !Mathf.Approximately(canvasGroup.alpha, targetAlpha)) { canvasGroup.alpha = Mathf.MoveTowards(canvasGroup.alpha, targetAlpha, speed * Time.unscaledDeltaTime); yield return null; } if (canvasGroup != null) canvasGroup.alpha = targetAlpha; } }