Add a loading screen between scenes

This commit is contained in:
Michal Pikulski
2025-10-13 10:41:58 +02:00
parent ab84c97675
commit 447d33fe55
9 changed files with 919 additions and 381 deletions

View File

@@ -0,0 +1,168 @@
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using Core;
namespace UI
{
/// <summary>
/// Controls the loading screen UI display, progress updates, and timing
/// </summary>
public class LoadingScreenController : MonoBehaviour
{
[Header("UI References")]
[SerializeField] private GameObject loadingScreenContainer;
[SerializeField] private Image progressBarImage;
[Header("Settings")]
[SerializeField] private float minimumDisplayTime = 1.0f;
[SerializeField] private float progressUpdateInterval = 0.1f;
private float _displayStartTime;
private Coroutine _progressCoroutine;
private bool _loadingComplete = false;
private bool _animationComplete = false;
private void Awake()
{
if (loadingScreenContainer == null)
loadingScreenContainer = gameObject;
// Ensure the loading screen is initially hidden
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(false);
}
}
/// <summary>
/// Shows the loading screen and resets the progress bar to zero
/// </summary>
public void ShowLoadingScreen()
{
// Stop any existing progress coroutine
if (_progressCoroutine != null)
{
StopCoroutine(_progressCoroutine);
_progressCoroutine = null;
}
_displayStartTime = Time.time;
_loadingComplete = false;
_animationComplete = false;
if (progressBarImage != null)
{
progressBarImage.fillAmount = 0f;
}
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(true);
}
// Start the progress filling coroutine
_progressCoroutine = StartCoroutine(AnimateProgressBar());
}
/// <summary>
/// Animates the progress bar at a steady pace over the minimum display time,
/// while also checking actual loading progress from SceneManagerService
/// </summary>
private IEnumerator AnimateProgressBar()
{
float startTime = Time.time;
// Continue until both animation and loading are complete
while (!_animationComplete)
{
// Calculate the steady progress based on elapsed time
float elapsedTime = Time.time - startTime;
float steadyProgress = Mathf.Clamp01(elapsedTime / minimumDisplayTime);
// Get the actual loading progress from SceneManagerService
float actualProgress = 0f;
if (SceneManagerService.Instance != null)
{
actualProgress = SceneManagerService.Instance.GetAggregateLoadProgress();
}
// If loading is complete, actualProgress should be 1.0
if (_loadingComplete)
{
actualProgress = 1.0f;
}
// Use the minimum of steady progress and actual progress
// This ensures we don't show more progress than actual loading
float displayProgress = Mathf.Min(steadyProgress, actualProgress);
// Log the progress values for debugging
Debug.Log($"[LoadingScreen] Progress - Default: {steadyProgress:F2}, Actual: {actualProgress:F2}, Display: {displayProgress:F2}");
// Directly set the progress bar fill amount without smoothing
if (progressBarImage != null)
{
progressBarImage.fillAmount = displayProgress;
}
// Check if the animation has completed
// Animation is complete when we've reached the minimum display time AND we're at 100% progress
if (steadyProgress >= 1.0f && displayProgress >= 1.0f)
{
_animationComplete = true;
Debug.Log("[LoadingScreen] Animation complete");
break;
}
// Wait for the configured interval before updating again
yield return new WaitForSeconds(progressUpdateInterval);
}
// Ensure we end at 100% progress
if (progressBarImage != null)
{
progressBarImage.fillAmount = 1.0f;
Debug.Log("[LoadingScreen] Final progress set to 1.0");
}
// Hide the screen if loading is also complete
if (_loadingComplete)
{
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(false);
Debug.Log("[LoadingScreen] Animation AND loading complete, hiding screen");
}
}
_progressCoroutine = null;
}
/// <summary>
/// Called when the actual loading process is complete
/// </summary>
public void HideLoadingScreen()
{
Debug.Log("[LoadingScreen] Loading complete, marking loading as finished");
// Mark that loading is complete
_loadingComplete = true;
// If animation is already complete, we can hide the screen now
if (_animationComplete)
{
if (loadingScreenContainer != null)
{
loadingScreenContainer.SetActive(false);
Debug.Log("[LoadingScreen] Animation already complete, hiding screen immediately");
}
}
else
{
Debug.Log("[LoadingScreen] Animation still in progress, waiting for it to complete");
// The coroutine will handle hiding when animation completes
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1494b10574e74acd880f9101b4248239
timeCreated: 1760341032

View File

@@ -1,4 +1,5 @@
using System;
using Core;
using UnityEngine;
using UnityEngine.SceneManagement;

View File

@@ -1,4 +1,5 @@
using System;
using Core;
using UnityEngine;
using UnityEngine.SceneManagement;
using Input;