A Complete Guide to Unity's Scene Management
A step-by-step guide on how to properly switch between levels, menus, and different areas without breaking everything, from a developer who learned the hard way.
Here's the thing - I still remember the exact moment my first Unity game completely fell apart. I was three months into my passion project at KIXEYE, feeling pretty confident about my level design, when I decided to add "just one more level." Clicked play, hit my "Next Level" button, and... black screen. Complete freeze. Had to force-quit Unity.
Turns out, I had zero clue how scene management actually worked. I was basically trying to build a multi-story house without understanding how doors work between rooms. That painful lesson taught me something crucial: scene management isn't just a technical feature - it's the backbone that holds your entire game together.
If you're building your first game and wondering how to properly switch between levels, menus, and different areas without breaking everything, you're in the right place. Let me show you the systematic approach I wish someone had taught me from day one.
Table of Contents
- What Scene Management Actually Does (And Why Your Game Needs It)
- The Building Blocks: Unity's Scene Management Vocabulary
- Three Ways to Load Scenes (And When Each One Makes Sense)
- Why I Always Use Async Loading Now (Even for Small Projects)
- My Go-To Scene Loading Patterns for Real Games
- How The Pros Handle Scene Transitions (Game Examples That Nailed It)
- Building Your First Scene Switcher (Step-by-Step Walkthrough)
- The Additive Loading Trick That Changed Everything
- Creating Loading Screens That Don't Suck
What Scene Management Actually Does (And Why Your Game Needs It)
Scene management in Unity is the backbone of a game's structure, handling the loading and unloading of different levels, menus, and areas. This solves the problem of organizing game content and creating a seamless player experience by providing a system to transition between different parts of the game.
Think of it like this - you know how a play has multiple acts, and the stage crew works behind the curtains to change the scenes without the audience seeing all that work? That's exactly what Unity's scene management does for your game. It allows developers to create everything from a simple main menu that leads to a gameplay level, to complex open-world games with dynamically loaded and unloaded areas.
Here's what I've learned after working on dozens of Unity projects: scene management gives you three massive advantages that every student developer needs to understand.
- Organized Project Structure keeps your game's content neatly organized into manageable chunks. Instead of having one massive scene with everything crammed in, you can separate your main menu, each level, boss fights, and cutscenes into their own scenes. Trust me, your future self will thank you when you're debugging at 2 AM.
- Improved Performance allows you to load only the necessary assets for a particular level, reducing memory usage and improving performance. When I was working on mobile games at KIXEYE, this was absolutely critical - you simply can't afford to have all your assets loaded at once on mobile devices.
- Enables Complex Gameplay makes it possible to create large, open-world games by dynamically loading and unloading parts of the world. Even if you're not building the next Breath of the Wild, understanding this concept will make you a much better developer.

The Building Blocks: Unity's Scene Management Vocabulary
Let me break down the key terms you'll encounter - I'll explain each abbreviation the first time since that always confused me as a beginner.
- Scene: A self-contained asset that holds a collection of GameObjects and their configurations, representing a level, a menu, or a specific part of your game. Think of it as a container for everything that belongs together.
- SceneManager: The primary static class in Unity for managing your scenes. It provides the functions to load, unload, and switch between scenes. This is your main tool for everything we're about to discuss.
- Build Settings: A crucial project-wide configuration where you must add all scenes that you intend to load at runtime. Each scene in the Build Settings is assigned a unique index. Here's something that tripped me up early on - if your scene isn't in Build Settings, you can't load it at runtime, period.
- LoadSceneMode.Single: This mode destroys all current GameObjects in the hierarchy before loading the new scene. It's the most common way to switch between levels - like completely changing the channel on TV.
- LoadSceneMode.Additive: This mode loads a new scene without destroying the GameObjects from the currently active scene. This is useful for loading UI, persistent managers, or creating complex game worlds - like adding a new layer to your scene.
- AsyncOperation: A class that allows you to monitor the progress of an asynchronous operation, such as loading a scene in the background. This is what prevents your game from freezing during level transitions.
Three Ways to Load Scenes (And When Each One Makes Sense)
After breaking enough games, I've learned there are three main approaches to loading scenes, and each has its place. Let me show you exactly how I implement each one.
Loading by Name: The Readable Approach
The most common way to load a scene is by using its name as a string. This is readable and easy to maintain, but it's prone to errors if you rename the scene file.
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
public void LoadLevel(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
}
I use this approach for most of my projects because it's clean and obvious what's happening. Just be careful about typos - I've spent embarrassing amounts of time debugging "Level_1" vs "Level1" mismatches.
Verified: Unity Docs - SceneManager.LoadScene
Loading by Index: The Fast Approach
You can also load a scene using its index from the Build Settings. This is faster than loading by name but can be brittle if you reorder scenes in the Build Settings.
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
public void LoadLevel(int sceneIndex)
{
SceneManager.LoadScene(sceneIndex);
}
}
I only use this when performance is absolutely critical, like in mobile games where every millisecond matters during transitions.
Asynchronous Loading: The Professional Approach
To prevent your game from freezing while a new scene is loading, you can load it asynchronously. This is essential for large levels.
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class AsyncSceneLoader : MonoBehaviour
{
public IEnumerator LoadLevelAsync(string sceneName)
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
while (!asyncLoad.isDone)
{
// You can use asyncLoad.progress to show a loading bar
yield return null;
}
}
}
Verified: Unity Docs - SceneManager.LoadSceneAsync
Why I Always Use Async Loading Now (Even for Small Projects)
Here's what I've learned from years of game development: the difference between synchronous and asynchronous loading isn't just technical - it's about player experience.
| Criteria | Approach A: LoadScene (Synchronous) |
Approach B: LoadSceneAsync (Asynchronous) |
|---|---|---|
| Best For | Simple menus, small levels, or situations where a short loading pause is acceptable. | Large levels, complex scenes, or when you want to provide a seamless loading experience with a loading screen. |
| Performance | Can cause a noticeable stutter or freeze in the game while the new scene is being loaded. | Loads the scene in the background, preventing the game from freezing and allowing for a smoother player experience. |
| Complexity | Very simple to implement, requiring only a single line of code. | Slightly more complex, requiring a coroutine to manage the loading process and check for completion. |
| Code Example | SceneManager.LoadScene("Level_1"); |
StartCoroutine(LoadLevelAsync("Level_1")); |
Even for small projects, I always go with async loading now. That extra bit of complexity pays off the moment your levels get even slightly larger, and your players will notice the difference.
My Go-To Scene Loading Patterns for Real Games
After working on multiple Unity projects, I've developed a few patterns that I use repeatedly. Let me share the ones that have saved me the most headaches.
The Loading Scene Pattern
For a professional feel, use a dedicated loading scene with a progress bar to transition between levels. This is what I implement in every game now:
// In your loading scene script
public class LoadingScreen : MonoBehaviour
{
void Start()
{
// Get the name of the scene to load from a static variable or PlayerPrefs
string sceneToLoad = "Level_1";
StartCoroutine(LoadLevelAsync(sceneToLoad));
}
IEnumerator LoadLevelAsync(string sceneName)
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
while (!asyncLoad.isDone)
{
// Update a progress bar with asyncLoad.progress
yield return null;
}
}
}
Verified: Unity Learn - Creating a Loading Screen
The Persistent Manager Pattern
Use additive loading for persistent elements. Keep a "manager" scene loaded additively to handle persistent systems like audio, game state, or player data.
void Start()
{
SceneManager.LoadScene("ManagerScene", LoadSceneMode.Additive);
}
This pattern has been a game-changer for me. Instead of trying to make GameObjects persist between scenes (which is always messy), I just keep a manager scene loaded that handles all the persistent stuff.
How The Pros Handle Scene Transitions (Game Examples That Nailed It)
Let me tell you about how some of my favorite games handle scene management - these examples have shaped how I think about level transitions in my own projects.
The Legend of Zelda: Breath of the Wild - Seamless World Loading
What I find fascinating about this approach: The massive open world is seamlessly loaded as the player travels, with no loading screens between areas.
The Implementation: The game likely uses a form of additive and asynchronous loading to stream in new areas of the map as the player approaches them, and unload areas that are far away.
The Player Experience: The player feels a sense of freedom and immersion, able to explore a vast world without interruption.
When I analyzed how this works, it completely changed my perspective on what's possible with smart scene management. You're not limited to discrete levels - you can create truly seamless experiences.
Super Mario Odyssey - Clear Level Progression
What makes this brilliant: Each kingdom is a separate, large level that the player travels to from the Odyssey ship.
The Implementation: The game uses LoadScene to transition between the Odyssey and the different kingdoms.
The Player Experience: The player has a clear sense of progression as they unlock and travel to new kingdoms.
This is why I always recommend studying this game's approach - it shows how simple scene transitions can still feel magical when done with intention.
Hollow Knight - Connected World Magic
What I love about this implementation: The game's world is a large, interconnected map, but it's divided into smaller scenes that are loaded as the player moves between them.
The Implementation: The game likely uses additive loading to connect different areas, with triggers at the edge of a scene that start loading the next one.
The Player Experience: The player experiences a large, interconnected world that feels like a single, cohesive space, while still benefiting from the performance of smaller, individual scenes.
After analyzing dozens of games, this stands out because it proves you can have the best of both worlds - performance optimization and seamless exploration.
Building Your First Scene Switcher (Step-by-Step Walkthrough)
Alright, let's get our hands dirty. I'm going to walk you through creating your first scene management system exactly the way I approach it in my projects.
Simple Level Switcher: Your First Implementation
Scenario Goal: Create a simple main menu with a button that loads the first level of the game.
Here's the exact method I use when starting any new project:
Unity Editor Setup:
- Create two scenes: "MainMenu" and "Level1"
- In the "MainMenu" scene, create a UI Button
- Create an empty GameObject named "SceneSwitcher"
Step-by-Step Code Implementation:
- Create a new C# script called
SceneSwitcherand attach it to the "SceneSwitcher" GameObject. - Add the
UnityEngine.SceneManagementnamespace. - Create a public method to load a scene by name:
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneSwitcher : MonoBehaviour
{
public void LoadLevel(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
}
- In the Unity Editor, select the UI Button and in the
OnClick()event, drag the "SceneSwitcher" GameObject into the object field. - From the function dropdown, select
SceneSwitcher > LoadLevel(string). - In the text field, enter "Level1".
- Add both "MainMenu" and "Level1" to the Build Settings.
This is exactly how I set up every project's basic navigation. It's simple, reliable, and you can expand on it later.
The Additive Loading Trick That Changed Everything
Let me show you something that took me months to figure out when I was starting out - additive loading for persistent UI and managers.
Persistent UI Implementation
Scenario Goal: Create a UI scene that stays loaded across multiple gameplay levels.
When I'm working on projects that need persistent elements, my process is:
Unity Editor Setup:
- Create three scenes: "ManagerScene", "Level1", and "Level2"
- In "ManagerScene", create a UI Canvas with some text or a button
- Create an empty GameObject named "GameManager"
Step-by-Step Code Implementation:
- Create a new C# script called
GameManagerand attach it to the "GameManager" GameObject. - Add the
UnityEngine.SceneManagementnamespace. - In the
Start()method, load the first level additively:
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
void Start()
{
// Load the first level additively
SceneManager.LoadScene("Level1", LoadSceneMode.Additive);
}
public void LoadNextLevel()
{
// Unload the current level and load the next one
SceneManager.UnloadSceneAsync("Level1");
SceneManager.LoadScene("Level2", LoadSceneMode.Additive);
}
}
- Add all three scenes to the Build Settings. When you run the "ManagerScene", "Level1" will be loaded alongside it, and the UI will be visible.
I've used this pattern in dozens of projects now. It's incredibly powerful once you get the hang of it.
Creating Loading Screens That Don't Suck
Here's something I learned the hard way at KIXEYE - players hate loading screens, but they hate freezing games even more. The solution is to make loading screens that actually provide value.
Asynchronous Loading with Progress Bar
Scenario Goal: Create a loading screen that shows the progress of loading a large level.
These are the exact settings I use for professional loading screens:
Unity Editor Setup:
- Create three scenes: "MainMenu", "LoadingScreen", and "LargeLevel"
- In the "LoadingScreen" scene, create a UI Slider
- Create an empty GameObject named "LoadingManager"
Step-by-Step Code Implementation:
- Create a static class to hold the name of the scene to be loaded:
public static class SceneLoaderData
{
public static string sceneToLoad;
}
- In the "MainMenu" script, when the play button is clicked, set the
sceneToLoadand load the "LoadingScreen":
public void PlayGame()
{
SceneLoaderData.sceneToLoad = "LargeLevel";
SceneManager.LoadScene("LoadingScreen");
}
- Create a new C# script called
LoadingManagerand attach it to the "LoadingManager" GameObject in the "LoadingScreen" scene. - In the
LoadingManagerscript, use a coroutine to load the scene asynchronously and update the slider:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LoadingManager : MonoBehaviour
{
public Slider progressBar;
void Start()
{
StartCoroutine(LoadLevelAsync());
}
IEnumerator LoadLevelAsync()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(SceneLoaderData.sceneToLoad);
while (!asyncLoad.isDone)
{
progressBar.value = asyncLoad.progress;
yield return null;
}
}
}
- Add all three scenes to the Build Settings.
I've configured this dozens of times, and this is my go-to setup. The progress bar gives players something to watch, and the async loading keeps everything smooth.
Key Takeaways
- Scene management is the backbone of game structure - it organizes content, improves performance, and enables complex gameplay by handling loading and unloading of different game areas.
- Always use asynchronous loading for better player experience - AsyncOperation prevents game freezing and allows for smooth loading screens, even on smaller projects.
- Master the three loading approaches - loading by name (readable), by index (fast), and asynchronously (professional) each serve different purposes in game development.
- Additive loading is essential for persistent elements - use LoadSceneMode.Additive to keep UI, managers, and persistent systems loaded across level transitions.
- Build Settings configuration is critical - every scene you want to load at runtime must be added to Build Settings with proper indexing.
- Loading screens add professional polish - implement progress bars and smooth transitions instead of letting players stare at frozen screens.
- Study successful game implementations - analyze how games like Breath of the Wild, Mario Odyssey, and Hollow Knight handle scene transitions for inspiration.
- Start simple and build complexity gradually - begin with basic scene switching, then add async loading, additive scenes, and advanced loading screens as your skills develop.
Common Questions
Scene management in Unity is the system that handles loading and unloading different levels, menus, and areas of your game. You need it to organize your game content, improve performance by only loading necessary assets, and create smooth transitions between different parts of your game. Without proper scene management, you'd have everything crammed into one massive scene, which would be a nightmare to debug and would perform poorly.
LoadSceneMode.Single destroys all current GameObjects before loading the new scene - it's like completely changing the channel on TV. LoadSceneMode.Additive loads a new scene while keeping existing GameObjects - like adding a new layer to your current scene. Use Single for normal level transitions, and Additive for persistent UI, managers, or complex world streaming.
Always use asynchronous loading (LoadSceneAsync) when you want to prevent your game from freezing during scene transitions. This is essential for large levels, mobile games, or any time you want to show a loading screen with progress bars. Even for smaller projects, async loading provides a much better player experience and makes your game feel more professional.
Create a dedicated loading scene with a UI Slider, then use AsyncOperation.progress to update the slider value while loading your target scene asynchronously. Store the target scene name in a static variable, load your loading scene first, then in the loading scene script, start a coroutine that loads the target scene and updates the progress bar until AsyncOperation.isDone returns true.
Build Settings is Unity's project-wide configuration where you must add all scenes that you intend to load at runtime. Each scene gets assigned a unique index. If your scene isn't in Build Settings, you can't load it during runtime - this is a common beginner mistake that results in errors when trying to load scenes.
Use additive loading to keep a "manager" scene loaded that contains your persistent UI elements. Load this manager scene with LoadSceneMode.Additive at the start of your game, then load your gameplay levels additively as well. This way, your UI stays visible while you can unload and load different gameplay areas underneath it.
Create separate scenes for different purposes: main menu, each level, loading screens, and persistent managers. Name them clearly (like "MainMenu", "Level_01", "LoadingScreen") and organize them logically in your Build Settings. This makes your project easier to navigate, allows team members to work on different areas simultaneously, and improves performance.
Use SceneManager.LoadSceneAsync() instead of SceneManager.LoadScene(). Wrap the async loading in a coroutine and use yield return null to prevent blocking the main thread. You can also check AsyncOperation.progress to show loading progress and only continue when AsyncOperation.isDone is true.
Loading by name uses the scene's filename as a string (like "Level_1") and is more readable and maintainable. Loading by index uses the scene's position in Build Settings and is slightly faster but more fragile if you reorder scenes. Use names for most situations unless you need the small performance boost that indices provide.
Large open-world games use advanced additive and asynchronous loading to stream in new areas as the player approaches them while unloading distant areas. They typically divide the world into grid sections, use player position to determine what to load/unload, and preload adjacent areas to maintain seamless transitions. This requires careful memory management and LOD (Level of Detail) systems to maintain performance.