178 lines
6.0 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
using UnityEngine.UI;
namespace BulletHellTemplate
{
/// <summary>
/// Manages the loading screen during scene transitions.
/// Displays a "Loading" text with animated dots and ensures a minimum loading time.
/// Shows loading progress percentage and handles pooling progress.
/// </summary>
public class LoadingManager : MonoBehaviour
{
public static LoadingManager Singleton;
[Header("UI Elements")]
[Tooltip("Text component displaying the animated 'Loading' message.")]
public TextMeshProUGUI loadingText;
[Tooltip("UI containerPassItems holding the loading screen.")]
public GameObject UILoading;
[Tooltip("Slider displaying loading progress.")]
public Slider loadingProgressBar;
[Header("Loading Settings")]
[Tooltip("Minimum duration (in seconds) the loading screen should be displayed.")]
public float minimumLoadingTime = 2f;
[Header("Loading AudioClip")]
public AudioClip loadingAudioClip;
public string Loadingtag = "master";
[HideInInspector]
public bool isLoading = false;
private bool _running;
private float _minTime;
private float dotTimer = 0f;
private int dotCount = 0;
private void Awake()
{
// Singleton pattern to ensure only one instance exists
if (Singleton == null)
{
Singleton = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// Loads a scene asynchronously with a loading screen.
/// Now includes pooling progress and updates the progress bar.
/// Handles scenes without `GameplayManager`.
/// </summary>
/// <param name="sceneName">The name of the scene to load.</param>
/// <returns>An IEnumerator for coroutine execution.</returns>
public IEnumerator LoadSceneWithLoadingScreen(string sceneName)
{
isLoading = true;
AudioManager.Singleton.PlayLoadingMenu(loadingAudioClip, Loadingtag);
UILoading.SetActive(true);
float startTime = Time.time;
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
asyncLoad.allowSceneActivation = false;
float simulatedProgress = 0f;
float simulatedProgressRate = 1f / minimumLoadingTime;
float totalProgress = 0f;
while (!asyncLoad.isDone)
{
float sceneProgress = Mathf.Clamp01(asyncLoad.progress / 0.9f);
simulatedProgress += simulatedProgressRate * Time.deltaTime;
totalProgress = Mathf.Min(sceneProgress, simulatedProgress);
if (loadingProgressBar != null)
{
loadingProgressBar.value = totalProgress;
}
if (loadingText != null)
{
int progressPercentage = Mathf.RoundToInt(totalProgress * 100f);
loadingText.text = $"{LanguageManager.LanguageManager.Instance.GetTextEntryByID("loading_loading")}{GetAnimatedDots()}\n{progressPercentage}%";
}
if (asyncLoad.progress >= 0.9f && (Time.time - startTime >= minimumLoadingTime))
{
asyncLoad.allowSceneActivation = true;
}
yield return null;
}
if (asyncLoad.isDone)
{
if (UILoading.activeSelf)
{
UILoading.SetActive(false);
}
AudioManager.Singleton.StopLoadingAudioPlay();
}
isLoading = false;
}
/// <summary>
/// Called to open the loading screen. Used during scene loading with Photon Fusion.
/// </summary>
/// <param name="minTime">Minimum duration the loading screen should remain visible.</param>
public void Open(float minTime = 2f)
{
// Prevent reopening if already running
if (_running) return;
isLoading = true;
_minTime = minTime;
// Start the loading coroutine (used during Fusion scene transitions)
StartCoroutine(SimpleLoader());
}
/// <summary>
/// Called to close the loading screen. Used after Photon Fusion scene load is completed.
/// </summary>
public void Close()
{
_running = false;
}
private IEnumerator SimpleLoader()
{
_running = true;
AudioManager.Singleton.PlayLoadingMenu(loadingAudioClip, Loadingtag);
UILoading.SetActive(true);
float t0 = Time.time;
while (_running || Time.time - t0 < _minTime)
{
float pct = Mathf.InverseLerp(0, _minTime, Time.time - t0);
if (loadingProgressBar) loadingProgressBar.value = pct;
if (loadingText)
loadingText.text =
$"{LanguageManager.LanguageManager.Instance.GetTextEntryByID("loading_loading")}{GetAnimatedDots()}\n{Mathf.RoundToInt(pct * 100)}%";
yield return null;
}
UILoading.SetActive(false);
AudioManager.Singleton.StopLoadingAudioPlay();
isLoading = false;
}
/// <summary>
/// Returns a string with animated dots based on time.
/// </summary>
/// <returns>A string with 0 to 3 dots.</returns>
private string GetAnimatedDots()
{
dotTimer += Time.deltaTime;
if (dotTimer >= 0.5f)
{
dotTimer = 0f;
dotCount = (dotCount + 1) % 4;
}
return new string('.', dotCount);
}
}
}