Source file unity-csharp/scene-flow/LoadingScreen.cs from the GDnD code examples. Download raw file
// GDnD wiki example
// Demonstrates: SceneManager.LoadSceneAsync with a progress bar and allowSceneActivation
// Related pages: [[unity-scene-management]]
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
// Put this on the Title scene's Canvas. The loading panel is an overlay in the
// current scene; it disappears by itself when the new scene activates.
public class LoadingScreen : MonoBehaviour
{
[SerializeField] private GameObject loadingPanel;
[SerializeField] private Slider progressBar; // Min 0, Max 1
[SerializeField] private float minimumShowSeconds = 0.75f; // small scenes load too fast to see
private bool isLoading;
// Wire a Play button's On Click () to this and type the scene name.
public void LoadWithProgress(string sceneName)
{
if (!isLoading)
{
StartCoroutine(LoadRoutine(sceneName));
}
}
private IEnumerator LoadRoutine(string sceneName)
{
isLoading = true;
Time.timeScale = 1f;
if (loadingPanel != null)
{
loadingPanel.SetActive(true);
}
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
if (operation == null)
{
isLoading = false; // scene missing from the scene list; Unity has logged why
yield break;
}
// Hold the new scene back so the bar can reach the end first.
// While activation is held, progress stops at 0.9 and isDone stays false.
operation.allowSceneActivation = false;
float shownFor = 0f;
while (operation.progress < 0.9f || shownFor < minimumShowSeconds)
{
shownFor += Time.unscaledDeltaTime;
if (progressBar != null)
{
progressBar.value = Mathf.Clamp01(operation.progress / 0.9f);
}
yield return null;
}
if (progressBar != null)
{
progressBar.value = 1f;
}
operation.allowSceneActivation = true; // the new scene replaces this one
}
}