Version: Unity 6.7 Alpha (6000.7)
Language : English
Reference content in a content directory
Load content directories

Include scenes in a content build

Unity builds the scenesA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary
in the Scene List of the Build ProfileA set of customizable configuration settings to use when creating a build for your target platform. More info
See in Glossary
window directly into a Player build rather than including them in a content build. When the Player starts up, Unity automatically loads the first scene in the list.

To keep builds efficient, create one startup scene in the Scene List which serves as access to the content in a content directory build. This approach avoids asset duplication and keeps all content within the content directory build.

This single startup scene typically contains one or more MonoBehaviour components that register the content directory at runtime, then load one or more scenes and other initial content from it.

Include scenes in a content directory

To include scenes in a content directory, use LoadableSceneId. You can also use this struct to reference those scenes from scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
and from the Unity Editor.

You can use LoadableSceneId as a field type in MonoBehaviour and ScriptableObject-derived classes. You can assign a scene to a field of type LoadableSceneId while authoring content in the Editor, either through the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary
or from scripts.

// Example of assigning a LoadableSceneId field from scripting
myMonoBehaviour.m_Scene = LoadableSceneIdEditorUtility.CreateLoadableSceneId(scenePath);

Internally LoadableSceneId uses the Asset Database GUID as a unique identifier for the scene. This means that the reference continues to work even if you rename the scene asset or move it within the project.

When you build a content directory, Unity recursively walks the root assets and all their dependencies to find every scene referenced by a LoadableSceneId. Unity automatically includes every referenced scene in the build output, and also walks into each scene to pull in any other dependencies the scene requires. Therefore, LoadableSceneId references aren’t limited to root assets, and the build includes any scene referenced by a LoadableSceneId field on any object reachable from the root assets.

At runtime and in Play mode, you can use LoadableSceneId fields with the SceneManager API to load and unload scenes. You must register the content directory containing the scene before loading the scene. For more information on registering content directories, refer to Load content directories.

Note: Loadable<T> isn’t compatible with scenes, because your application might need to load scenes multiple times. LoadableSceneId is the scene-oriented counterpart to LoadableObjectId, which is used for assets.

Runtime loading of scenes

To load scenes in the Player or Play mode, call the following:

AsyncOperation SceneManager.LoadSceneAsync(Unity.Loading.LoadableSceneId, LoadSceneParameters);

The call returns an AsyncOperation instance that you can use to track the asynchronous load. A common pattern is to subscribe to AsyncOperation.completed and then call SceneManager.GetSceneByLoadableSceneId(loadableSceneId) from the callback to retrieve the loaded Scene.

You can load scenes one by one, or additively through the LoadSceneParameters argument. In Single mode all other open scenes are closed. In Additive mode, scenes that are already loaded remain open. Refer to SceneManagement.LoadSceneMode for more information.

If two LoadableSceneId values reference the same scene and you call LoadSceneAsync on each in Additive mode, Unity loads the scene twice as two distinct scene instances.

To unload scenes, call UnloadSceneAsync.

For example, a startup scene can contain a MonoBehaviour with LoadableSceneId fields that reference other scenes. You can assign the scenes in the Inspector while authoring, and at runtime scripts can load and unload scenes in response to events such as character movement or button presses.

The following example loads two scenes additively at startup and unloads one in response to an event:

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using Unity.Loading;

public class SceneLoader : MonoBehaviour
{
    // Use the Inspector to assign scenes to these fields.
    [SerializeField]
    LoadableSceneId m_CubeSceneReference;

    [SerializeField]
    LoadableSceneId m_SphereSceneReference;

    // Store references to the loaded scenes so you can unload them later.
    Scene m_CubeScene;
    Scene m_SphereScene;

    void Start()
    {
        // LoadSceneMode.Additive loads the new scene alongside the current scene.
        // Use LoadSceneMode.Single instead if you want to replace the current scene.
        AsyncOperation cubeLoad = SceneManager.LoadSceneAsync(m_CubeSceneReference, new LoadSceneParameters(LoadSceneMode.Additive));

        // completed fires when the load finishes. Retrieve the Scene object at that
        // point so you can unload it later. The _ parameter is the completed AsyncOperation, which isn't needed here.
        cubeLoad.completed += _ => { m_CubeScene = SceneManager.GetSceneByLoadableSceneId(m_CubeSceneReference); };

        StartCoroutine(WaitAndLoadAnotherScene(1.0f));
    }

    // Loads a second scene additively after a delay.
    private IEnumerator WaitAndLoadAnotherScene(float delay)
    {
        yield return new WaitForSeconds(delay);
        AsyncOperation sphereLoad = SceneManager.LoadSceneAsync(m_SphereSceneReference, new LoadSceneParameters(LoadSceneMode.Additive));
        sphereLoad.completed += _ => { m_SphereScene = SceneManager.GetSceneByLoadableSceneId(m_SphereSceneReference); };
    }

    // Call in response to a game event, such as a button press.
    public void WhenSomeEventHappens()
    {
        // Check isLoaded before unloading: the scene might still be loading
        // when this method is called.
        if (m_CubeScene.isLoaded)
            SceneManager.UnloadSceneAsync(m_CubeScene);
    }

    // Unload both scenes when this MonoBehaviour is destroyed to free memory.
    void OnDestroy()
    {
        if (m_CubeScene.isLoaded)
            SceneManager.UnloadSceneAsync(m_CubeScene);

        if (m_SphereScene.isLoaded)
            SceneManager.UnloadSceneAsync(m_SphereScene);
    }
}

LoadableSceneId usage examples

The following are examples of how to use LoadableSceneId in your project. You can use more than one of these patterns in the same build.

Transition between scenes

A scene can contain a MonoBehaviour that unloads the current scene and loads a different one when a condition is met. This pattern suits projects where only a single scene is active at a time, such as games that transition between levels or regions of a large 3D world.

The following example transitions to a target scene when a character enters a 2D trigger:

using UnityEngine;
using UnityEngine.SceneManagement;

[RequireComponent(typeof(Collider2D))]
public class SceneTransition : MonoBehaviour
{
    public Unity.Loading.LoadableSceneId TargetScene;

    private void OnTriggerEnter2D(Collider2D col)
    {
        if (TargetScene.IsValid)
            SceneManager.LoadSceneAsync(TargetScene, new LoadSceneParameters(LoadSceneMode.Single));
    }
}

With this pattern you don’t need to maintain a separate list of scenes to build, unlike AssetBundles or Addressables, where you assign each scene to an AssetBundle or group. However, scene references are spread across your project instead of in a central root asset, which means it’s difficult to understand how many scenes a build includes. An alternative is to centralize scenes in a root asset, as described in the following section.

Centralize scenes in a root asset

For projects with many scenes, a ScriptableObject-derived class that holds a list of LoadableSceneId fields provides a single, visible record of all scenes in the build. This makes it easier to understand which scenes are in your project and gives a central place to manage scene loading logic, rather than spreading references across many MonoBehaviour objects inside scenes.

Use ContentLoadManager.GetRootAssets<T> at runtime to retrieve the root asset from a registered content directory.

The following example defines a scene list with named fields for a main menu, a UI scene, and an array of levels:

using UnityEngine;
using Unity.Loading;

public class CustomSceneList : ScriptableObject
{
    public LoadableSceneId MainMenu;
    public LoadableSceneId UI;
    public LoadableSceneId[] Levels;

    // Include a single asset of this type in the root asset list.
    // Use this method to retrieve it in the Player or during Editor Play mode.
    static public CustomSceneList Get()
    {
        return ContentLoadManager.GetRootAssets<CustomSceneList>()[0];
    }
}

Find scenes from a content directory

You can build scenes into a separate content directory and allow code in the Player build to discover them at runtime. Register the content directory with ContentLoadManager.RegisterContentDirectory, retrieve the root asset with ContentLoadManager.GetRootAssets<T>, then load the scene with SceneManager.LoadSceneAsync.

The following example registers a content directory that contains a DLCSceneList root asset and loads a bonus scene from it:

using System;
using System.Collections;
using UnityEngine;
using Unity.Loading;
using UnityEngine.SceneManagement;

public class DLCSceneList : ScriptableObject
{
    public LoadableSceneId m_bonusScene;
}

public class LoadSceneFromRootAsset
{
    public static IEnumerator LoadBonusScene(string contentDirectoryPath, Action<Scene> onSceneLoaded)
    {
        ContentLoadManager.RegisterContentDirectory(contentDirectoryPath);
        DLCSceneList root = ContentLoadManager.GetRootAssets<DLCSceneList>()[0];
        LoadableSceneId sceneReference = root.m_bonusScene;
        AsyncOperation op = SceneManager.LoadSceneAsync(sceneReference, new LoadSceneParameters(LoadSceneMode.Additive));

        yield return op;

        Scene loadedScene = SceneManager.GetSceneByLoadableSceneId(sceneReference);
        onSceneLoaded?.Invoke(loadedScene);
    }
}

Important: Avoid building the same scene into both the Player build and a content directory. This duplicates the scene and its dependencies in the build output, increasing build size. There’s no public API for selecting which copy loads at runtime, so the result is unpredictable.

Additional resources

Reference content in a content directory
Load content directories