Projext/Assets/00001.Scripts/SceneLoader.cs

207 lines
6.8 KiB
C#
Raw Normal View History

2026-02-22 13:37:34 +00:00
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using TMPro;
public class SceneLoader : MonoBehaviour
{
// =========================
// 싱글톤(전역 접근용)
// =========================
public static SceneLoader Instance;
// =========================
// 로딩 UI 연결
// =========================
[Header("로딩 UI 연결")]
public GameObject loadingCanvas; // 하이어라키의 'load canvas' 전체(로딩 화면 전체)
public CanvasGroup backgroundGroup; // 배경(검정 페이드)용 CanvasGroup
public TextMeshProUGUI tipText; // Tip 텍스트(TMP)
// =========================
// 로딩 시 나타날 요소들
// =========================
[Header("로딩 시 나타날 요소들")]
public GameObject loadingTextObject; // "Loading..." 텍스트 오브젝트
public GameObject tipBarObject; // TipBar(막대) 오브젝트(부모일 수도 있음)
[Header("TipBar 실제 배경(선택)")]
public RectTransform tipBarBackgroundRect;
// =========================
// 설정
// =========================
[Header("설정")]
public string[] tips; // 랜덤으로 뽑을 팁 문구 배열
public float fadeDuration = 1.0f; // 배경 페이드 속도(초)
// =========================
// TipBar 자동 리사이즈 설정
// =========================
[Header("TipBar 자동 리사이즈(코드)")]
[Tooltip("Tip 텍스트 줄바꿈 기준 = 화면 폭의 몇 %를 쓸지")]
[Range(0.4f, 0.95f)]
public float wrapWidthScreenRatio = 0.75f;
[Tooltip("TipBar 안쪽 여백(좌/우 합, 상/하 합)")]
public Vector2 tipPadding = new Vector2(120f, 60f);
[Tooltip("TipBar 최소 높이")]
public float tipBarMinHeight = 70f;
// =========================
// 내부 캐시
// =========================
private RectTransform _tipBarRect;
private RectTransform _tipTextRect;
// private float _tipBarBaseHeight; // 사용하지 않는 변수이므로 삭제하여 경고 해결
[Header("TipBar 기본 높이(1줄 기준)")]
public float tipBarBaseHeight = 220f;
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<RectTransform>();
if (tipBarBackgroundRect != null)
_tipBarRect = tipBarBackgroundRect;
else if (tipBarObject != null)
_tipBarRect = tipBarObject.GetComponent<RectTransform>();
if (tipText != null)
{
tipText.enableWordWrapping = true;
tipText.overflowMode = TextOverflowModes.Overflow;
}
}
public void LoadSceneWithFade(string sceneName)
{
StartCoroutine(LoadProcess(sceneName));
}
private IEnumerator LoadProcess(string sceneName)
{
if (loadingTextObject != null) loadingTextObject.SetActive(false);
if (tipBarObject != null) tipBarObject.SetActive(false);
if (loadingCanvas != null) loadingCanvas.SetActive(true);
if (backgroundGroup != null) backgroundGroup.alpha = 0f;
// ★ 수정됨: Fade 호출 시 backgroundGroup을 함께 전달
yield return StartCoroutine(Fade(1f, backgroundGroup));
if (loadingTextObject != null) loadingTextObject.SetActive(true);
if (tipBarObject != null) tipBarObject.SetActive(true);
if (tipText != null)
{
if (tips != null && tips.Length > 0)
{
int randomIndex = Random.Range(0, tips.Length);
tipText.text = $"<color=#FFD700>Tip!</color> : {tips[randomIndex]}";
}
else
{
tipText.text = "";
}
ResizeTipBarToFitText();
yield return null;
ResizeTipBarToFitText();
}
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
op.allowSceneActivation = false;
float timer = 0f;
while (timer < 2.0f)
{
timer += Time.deltaTime;
yield return null;
}
op.allowSceneActivation = true;
if (loadingTextObject != null) loadingTextObject.SetActive(false);
if (tipBarObject != null) tipBarObject.SetActive(false);
// ★ 수정됨: Fade 호출 시 backgroundGroup을 함께 전달
yield return StartCoroutine(Fade(0f, backgroundGroup));
if (loadingCanvas != null) loadingCanvas.SetActive(false);
}
// =========================
// 배경 페이드 함수 (안전 코드 적용)
// =========================
private IEnumerator Fade(float targetAlpha, CanvasGroup canvasGroup)
{
if (canvasGroup == null)
{
Debug.LogWarning("SceneLoader: 페이드할 CanvasGroup이 없습니다!");
yield break;
}
// fadeDuration이 0인 경우 방지
float duration = Mathf.Max(0.01f, fadeDuration);
float speed = 1f / duration;
// null 체크 및 오차 범위 체크 추가
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;
}
}
private void ResizeTipBarToFitText()
{
if (tipText == null || _tipBarRect == null || _tipTextRect == null) return;
float scale = 1f;
var canvas = tipText.canvas;
if (canvas != null) scale = canvas.scaleFactor;
float safeWrapWidth = (Screen.width * wrapWidthScreenRatio) / Mathf.Max(0.0001f, scale);
safeWrapWidth = Mathf.Clamp(safeWrapWidth, 600f, 1400f);
float wrapWidth = Mathf.Max(200f, safeWrapWidth - tipPadding.x);
_tipTextRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, wrapWidth);
tipText.enableWordWrapping = true;
tipText.overflowMode = TextOverflowModes.Overflow;
tipText.ForceMeshUpdate();
Vector2 preferred = tipText.GetPreferredValues(tipText.text, wrapWidth, 0f);
float textHeight = Mathf.Ceil(preferred.y);
_tipTextRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, textHeight);
float neededHeight = textHeight + tipPadding.y;
float barHeight = Mathf.Max(tipBarBaseHeight, neededHeight, tipBarMinHeight);
_tipBarRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, barHeight);
}
}