using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; using TMPro; namespace BulletHellTemplate { /// /// 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. /// public class LoadingManager : MonoBehaviour { public static LoadingManager Singleton; [Header("UI Elements")] [Tooltip("Text component displaying the animated 'Loading' message.")] public TextMeshProUGUI loadingText; [Tooltip("UI container holding the loading screen.")] public GameObject UILoading; [Tooltip("Slider displaying loading progress.")] public UnityEngine.UI.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 void Awake() { // Singleton pattern to ensure only one instance exists if (Singleton == null) { Singleton = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } /// /// Loads a scene asynchronously with a loading screen. /// Now includes pooling progress and updates the progress bar. /// Handles scenes without `GameplayManager`. /// /// The name of the scene to load. /// An IEnumerator for coroutine execution. 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); float poolingProgress = 1f; if (GameplayManager.Singleton != null && !GameplayManager.Singleton.IsPoolingReady()) { poolingProgress = GameplayManager.Singleton.GetLoadingProgress(); } float actualTotalProgress = (sceneProgress + poolingProgress) / 2f; simulatedProgress += simulatedProgressRate * Time.deltaTime; totalProgress = Mathf.Min(actualTotalProgress, 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 && poolingProgress >= 1f && (Time.time - startTime >= minimumLoadingTime)) { asyncLoad.allowSceneActivation = true; } yield return null; } if (asyncLoad.isDone) { if (UILoading.activeSelf) { UILoading.SetActive(false); } AudioManager.Singleton.StopLoadingAudioPlay(); } isLoading = false; } private float dotTimer = 0f; private int dotCount = 0; /// /// Returns a string with animated dots based on time. /// /// A string with 0 to 3 dots. private string GetAnimatedDots() { dotTimer += Time.deltaTime; if (dotTimer >= 0.5f) { dotTimer = 0f; dotCount = (dotCount + 1) % 4; } return new string('.', dotCount); } } }