Files
EnglewoodLAB/Assets/Scripts/UVC/UI/Loading/UILoadingBar.cs

195 lines
7.8 KiB
C#

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