Include scenes in a content build
Use loadable references to reference and load scenes from a content directory at runtime.
阅读时间7 分钟最后更新于 1 个月前
Unity builds the scenes in the Scene List of the 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.
Build Profile
?
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 . You can also use this struct to reference those scenes from scripts and from the Unity Editor.
LoadableSceneIdYou can use as a field type in and -derived classes. You can assign a scene to a field of type while authoring content in the Editor, either through the Inspector or from scripts.
LoadableSceneIdMonoBehaviourScriptableObjectLoadableSceneId// Example of assigning a LoadableSceneId field from scriptingmyMonoBehaviour.m_Scene = LoadableSceneIdEditorUtility.CreateLoadableSceneId(scenePath);
Internally 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.
LoadableSceneIdUnity finds scenes the same way it finds any other content by starting at the root assets and recursively following tracked references. references aren't limited to root assets, so the build includes any scene referenced by a field on any object Unity reaches from the root assets. Unity also walks into each included scene to pull in the dependencies that scene requires. For more information, refer to Reference content in a content directory.
LoadableSceneIdLoadableSceneIdAt runtime and in Play mode, you can use fields with the 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.
LoadableSceneIdSceneManagerRuntime 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 instance that you can use to track the asynchronous load. A common pattern is to subscribe to and then call from the callback to retrieve the loaded .
AsyncOperationAsyncOperation.completedSceneManager.GetSceneByLoadableSceneId(loadableSceneId)SceneYou can load scenes one by one, or additively through the argument. In mode all other open scenes are closed. In mode, scenes that are already loaded remain open. Refer to for more information.
LoadSceneParametersSingleAdditiveSceneManagement.LoadSceneModeIf two values reference the same scene and you call on each in mode, Unity loads the scene twice as two distinct scene instances.
LoadableSceneIdLoadSceneAsyncAdditiveTo unload scenes, call .
UnloadSceneAsyncFor example, a startup scene can contain a MonoBehaviour with 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.
LoadableSceneIdThe 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 in your project. You can use more than one of these patterns in the same build.
LoadableSceneIdTransition 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 -derived class that holds a list of 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.
ScriptableObjectLoadableSceneIdUse at runtime to retrieve the root asset from a registered content directory.
ContentLoadManager.GetRootAssets<T>The following example defines a scene list with named fields for a main menu, a UI scene, and an array of levels:
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 , retrieve the root asset with , then load the scene with .
ContentLoadManager.RegisterContentDirectoryContentLoadManager.GetRootAssets<T>SceneManager.LoadSceneAsyncThe following example registers a content directory that contains a root asset, like the one defined in the previous section, and loads a level scene from it:
CustomSceneListpublic class LoadSceneFromRootAsset { // Reuses the CustomSceneList root asset defined in the previous example. public static IEnumerator LoadLevelScene(string contentDirectoryPath, Action<Scene> onSceneLoaded) { ContentLoadManager.RegisterContentDirectory(contentDirectoryPath); CustomSceneList root = ContentLoadManager.GetRootAssets<CustomSceneList>()[0]; LoadableSceneId sceneReference = root.Levels[0]; AsyncOperation op = SceneManager.LoadSceneAsync(sceneReference, new LoadSceneParameters(LoadSceneMode.Additive)); yield return op; Scene loadedScene = SceneManager.GetSceneByLoadableSceneId(sceneReference); onSceneLoaded?.Invoke(loadedScene); } }