Quick answer: The 0.9 cap is by design. With allowSceneActivation = false, the operation pauses at 90% waiting for permission to activate. Map your UI to progress / 0.9f so it shows 0–100%, then set activation true on user input.
Here is how to fix Unity scene loading that appears stuck forever at 90%. SceneManager.LoadSceneAsync with allowSceneActivation = false intentionally pauses to let you display a “Press any key to continue” prompt. Mapping the progress range correctly produces a clean 100% loading bar.
The Symptom
Loading bar fills to 90% and stays there. Player thinks the game is frozen. Setting allowSceneActivation = true jumps directly to the new scene without further progress display.
What Causes This
0.9 is the loading-only cap. The remaining 10% is the activation step: integrating the loaded scene, calling Awake/OnEnable on objects. With activation gated, the operation parks at 0.9.
Showing raw progress. Player sees 90% and assumes a hang.
No prompt for activation. Without UI letting players initiate activation, the loaded scene never appears.
The Fix
Step 1: Map progress 0–0.9 to 0–1.
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SceneLoader : MonoBehaviour
{
[SerializeField] private Slider progressBar;
[SerializeField] private GameObject pressAnyKeyHint;
public IEnumerator LoadScene(string name)
{
AsyncOperation op = SceneManager.LoadSceneAsync(name);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
progressBar.value = op.progress / 0.9f;
yield return null;
}
progressBar.value = 1f;
pressAnyKeyHint.SetActive(true);
while (!Input.anyKeyDown) yield return null;
op.allowSceneActivation = true;
while (!op.isDone) yield return null;
}
}
Step 2: For instant activation, leave allowSceneActivation default. If you do not need a Press Any Key prompt, do not set allowSceneActivation = false. Default true causes activation as soon as loading reaches 0.9, then progresses through 1.0.
Step 3: For multiple scenes, additive load.
AsyncOperation a = SceneManager.LoadSceneAsync("World", LoadSceneMode.Additive);
AsyncOperation b = SceneManager.LoadSceneAsync("UI", LoadSceneMode.Additive);
while (!a.isDone || !b.isDone) yield return null;
Each operation tracks its own progress.
Step 4: For Unity 2023+ async/await syntax.
async Awaitable LoadAsync(string name)
{
var op = SceneManager.LoadSceneAsync(name);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
progressBar.value = op.progress / 0.9f;
await Awaitable.NextFrameAsync();
}
op.allowSceneActivation = true;
}
“0.9 cap is by design. Map progress / 0.9 to your UI. Press Any Key prompt makes the cap a feature, not a bug.”
Related Issues
For async scene callback issues, see Async Scene Loading Callbacks. For async/await deadlocks, see async/await Deadlock.
Map 0-0.9 to 0-1. Press Any Key to activate. The bar reaches 100%.