using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; namespace UVC.UI.Loading { /// /// 로딩 UI의 표시와 숨김, 진행 상태를 관리하는 클래스입니다. /// CanvasGroup 컴포넌트를 사용하여 페이드 인/아웃 효과를 구현합니다. /// 이 클래스가 게임 오브젝트에 추가되면 CanvasGroup 컴포넌트도 자동으로 추가됩니다. /// [RequireComponent(typeof(CanvasGroup))] public class UILoadingBar : MonoBehaviour { /// /// 로딩 바 UI 프리팹이 있는 Resources 폴더 내의 경로입니다. /// Show() 메서드가 처음 호출될 때 이 경로를 사용하여 프리팹을 동적으로 생성합니다. /// public static string PrefabPath = "Prefabs/UI/Loading/UILoadingBar"; /// /// UILoadingBar의 유일한 인스턴스(Singleton)입니다. /// static으로 선언되어 어디서든 UILoadingBar.instance 형태로 접근할 수 있습니다. /// private static UILoadingBar instance; /// /// 로딩 진행률을 0.0에서 1.0 사이의 값으로 설정하거나 가져옵니다. /// 이 값은 로딩 이미지의 채워지는 양(fillAmount)에 직접 반영됩니다. /// /// /// /// // 로딩 진행률을 50%로 설정 /// UILoadingBar.Percent = 0.5f; /// /// public static float Percent { get { if (instance == null) return 0; return instance.loadinImage.fillAmount; } set { if (instance == null) return; instance.loadinImage.fillAmount = value; } } /// /// 로딩 화면에 표시될 메시지를 설정하거나 가져옵니다. /// /// /// /// // 로딩 메시지 설정 /// UILoadingBar.Message = "데이터를 불러오는 중입니다..."; /// /// public static string Message { get { if (instance == null) return ""; return instance.text.text; } set { if (instance == null) return; instance.text.text = value; } } /// /// 로딩 바를 화면에 표시합니다. /// 만약 로딩 바 인스턴스가 없다면 PrefabPath에서 프리팹을 불러와 생성합니다. /// /// 로딩 화면에 표시할 메시지입니다. /// /// /// // 기본 메시지로 로딩 바 표시 /// UILoadingBar.Show(); /// /// // 특정 메시지와 함께 로딩 바 표시 /// UILoadingBar.Show("플레이어 정보를 로딩 중입니다..."); /// /// public static void Show(string message = "") { if (instance == null) { GameObject prefab = Resources.Load(PrefabPath); GameObject go = Instantiate(prefab); go.name = "UILoadingBar"; go.transform.SetParent(null, false); instance = go.GetComponent(); } Message = message; instance.ShowLoading(); } /// /// 로딩 바를 화면에서 숨깁니다. /// 숨겨진 후에는 자동으로 파괴됩니다. /// /// /// /// // 로딩 완료 후 로딩 바 숨기기 /// UILoadingBar.Hide(); /// /// public static void Hide() { if (instance != null) { instance.HideLoading(); } } [Tooltip("페이드 인/아웃 효과를 제어하는 CanvasGroup 컴포넌트입니다. 알파 값을 조정하여 UI의 투명도를 변경합니다.")] [SerializeField] private CanvasGroup canvasGroup; // 페이드 효과를 제어하기 위한 CanvasGroup 컴포넌트 [Tooltip("로딩 진행 상태를 표시하는 이미지 컴포넌트입니다. 로딩 중 진행률을 시각적으로 나타냅니다.")] [SerializeField] private Image loadinImage; // 로딩 진행 상태를 표시하는 이미지 [Tooltip("로딩 메시지를 표시하는 텍스트 컴포넌트입니다. 로딩 중 사용자에게 정보를 제공합니다.")] [SerializeField] private TextMeshProUGUI text; // 로딩 메시지를 표시하는 텍스트 private float target = 0; // 애니메이션의 목표 알파 값 (0: 투명, 1: 불투명) private float duration = 0.25f; // 페이드 인/아웃 애니메이션 지속 시간 private bool animatting = false; // 현재 애니메이션이 진행 중인지 여부 /// /// 로딩 바를 부드럽게 나타나게 하는 애니메이션을 시작합니다. /// 이미 나타나는 중이면 다시 호출되지 않습니다. /// public void ShowLoading() { // 이미 애니메이션 중이고 목표 알파 값이 1(불투명)이면 중복 실행 방지 if (animatting && target == 1) return; target = 1; animatting = true; StopCoroutine("Animate"); // 이전에 실행 중이던 Animate 코루틴이 있다면 중지 StartCoroutine(Animate()); // Animate 코루틴 시작 } /// /// 로딩 바를 부드럽게 사라지게 하는 애니메이션을 시작합니다. /// 이미 사라지는 중이면 다시 호출되지 않습니다. /// public void HideLoading() { // 이미 애니메이션 중이고 목표 알파 값이 0(투명)이면 중복 실행 방지 if (animatting && target == 0) return; target = 0; animatting = true; StopCoroutine("Animate"); // 이전에 실행 중이던 Animate 코루틴이 있다면 중지 StartCoroutine(Animate()); // Animate 코루틴 시작 } /// /// CanvasGroup의 알파 값을 조절하여 페이드 인/아웃 효과를 주는 코루틴입니다. /// 코루틴은 특정 시간 동안 또는 특정 조건이 만족될 때까지 함수의 실행을 잠시 멈출 수 있는 특별한 함수입니다. /// private IEnumerator Animate() { float start = canvasGroup.alpha; // 애니메이션 시작 시점의 알파 값 float time = 0; // 애니메이션 경과 시간 // 경과 시간이 duration에 도달할 때까지 반복 while (time < duration) { time += Time.deltaTime; // 한 프레임 동안의 시간을 더해줌 // Mathf.Lerp를 사용하여 시작 알파 값과 목표 알파 값 사이를 부드럽게 보간 canvasGroup.alpha = Mathf.Lerp(start, target, time / duration); // 다음 프레임까지 대기 yield return null; } // 애니메이션이 끝난 후 목표 알파 값으로 정확히 설정 canvasGroup.alpha = target; animatting = false; // 만약 목표 알파 값이 0(사라지는 애니메이션)이었다면, 게임 오브젝트를 파괴 if (target == 0) { Destroy(gameObject); } } } }