Scene Manager
By loading a Lens in parts, you can dramatically improve Lens performance on device, which can increase reach, views, plays, and other engagement metrics. The Scene Manager custom component is necessary for organizing a Lens into scenes.
This powerful component enables easy scene management through functions like loadSceneSync
, loadSceneAsync
, unloadScene
, and unloadSceneByName
. The Scene Manager is essential for working with scenes in Lens Studio, whether you're building a multi-level game or a multi-layered lens.
This guide will walk through the basic functions and how to use it. With the Scene Manager, you can:
- Compartmentalize your lens into logical scenes, keeping your project organized.
- Quickly load and unload scenes as needed with simple functions.
- Manage scene transitions smoothly with async scene loading.
- Unload scenes by name to free up resources.
- Build multi-scene games, interactive stories, and more.
By following this guide and studying the Scene Manager Template, you'll learn how to leverage this powerful component and even improve Lens performance.
Adding Scene Manager
To use the Scene Manager custom component:
- Import the Scene Manager component from the Asset Library if it is not already present.
- Drag and drop the Scene Manager custom component into your Objects panel to create a scene object containing this component.
- Position the scene object with the Scene Manager component at the top of your Objects panel. This ensures the Scene Manager initializes before other parts of the project reference it.
- The Scene Manager will be accessible through the global.sceneManager object in scripts.
Now that we have our Scene Manager, we can prepare our scenes.
If you've installed Scene Manager before, you can just add the component as you would with any other component.
- Objects panel > + > Scene Object.
- Select the Scene Object.
- In the Inspector panel > + Add Component > Scene Manager.
Creating a Scene
Technically, a scene is simply an Object Prefab. To create an Object Prefab:
- Drag a Scene Object into the Resources panel
- Or right-click on a Scene Object and use the "Save as Prefab" option
If using the Scene Manager's asynchronous loading (loadSceneAsync
method), please remember to enable "Lazy Asset Loading" on the Object Prefab. This serializes/loads the Scene only when the Scene Manager loads it, improving the performance and speeding up the starting up speed of your Lens.
Registering the Scene to Scene Manager
Once you have created the needed Object Prefabs:
- Select the Scene Manager we created earlier.
- Click the "Add Value" button on the Scene Manager to add a new slot in the scene registry.
- Each registry item needs a name and prefab. Refer to the scene later using this name (case and space sensitive).
Scene Manager also supports Prefabs made into remote assets. This creates a Remote Scene registry item. Only asynchronous loading using the loadSceneAsync method is allowed for Remote Scenes, as the scene needs to be downloaded first.
Loading the Scene
You can load a scene by calling one of the two methods:
// Load a scene synchronously
global.sceneManager.loadSceneSync('scenename', {
// Optional parameters
additive: true, // Default value
enabled: true, // Default value
parent: undefined, // Default value
});
// Load a scene asynchronously
global.sceneManager.loadSceneAsync('scenename', {
// Optional parameters
additive: true, // Default value
enabled: true, // Default value
parent: undefined, // Default value
onProgress: (percentage) => {
Studio.log(`Loading progress: ${percentage * 100}%`);
}, // Default value is null
loadingScene: 'scenename', // You can specify a loading scene name here
onComplete: (loadedScene) => {
Studio.log('Scene has been loaded successfully');
}, // Default value is null
onFailure: (errorMsg) => {
Studio.error('Scene loading failed: ' + errorMsg);
}, // Default value is null
});
In many cases, you can load scenes without writing code using Behavior!
Consider the necessity of loading scenes with caution. Loading scenes may not be needed for small to mid-sized scenes that load instantly, as they can cause confusion. Implement loading scenes only for large, complex scenes that require additional loading time, or to display a splash screen for branding purposes before the experience begins. If you opt for a loading scene, set its minimum display time by assigning a value to `global.sceneManager.minLoadingTimeInSeconds`` (the default value is 0.1 seconds). This setting controls the minimum duration for which the loading scene appears.
Example
Take a look at the Scene Manager Template to see these capabilities in action.
APIs
Scene manager provides a set of useful properties and functions you can use throughout the global.sceneManager
object.
Here are the public API methods and properties for the SceneManager
class with more details:
Properties
verbose
:boolean
, can be written, controls verbose logging.extensions
:Array<SceneManagerExtension>
, readonly, array of extensions added to the scene manager.minLoadingTimeInSeconds
:number
, can be written, minimum on display in seconds for loading scenes, the default value is 0.1 (seconds).root
:SceneObject
, readonly, the root scene object to load scenes into.onSceneLoaded
:Event<LoadedScene>
, readonly, event fired when a scene is loaded.onSceneUnloaded
:Event<LoadedScene>
, readonly, event fired when a scene is unloaded.
Methods
loadSceneSync(name: string, options?: Object): LoadedScene
Loads a scene synchronously given a local scene name and optional parameters for additive loading, enabled state, and custom parent.
Parameters:
name
(required): The name of the scene to load.options
(optional): An object containing optional parameters.additive
(default: true): Whether the scene should be loaded additively.enabled
(default: true): Whether the scene should be loaded as enabled or disabled (hidden).parent
(default: null): If not null, the newly loaded scene will be placed under this Scene Object.
Returns:
newlyLoadedScene
: A LoadedScene object representing the newly loaded scene.
loadSceneAsync(name: string, options?: Object): Promise<LoadedScene
>
Loads a scene asynchronously given a name and optional parameters like onProgress callbacks, additive loading, custom parent, etc. Returns a Promise
.
Parameters:
name
(required): The name of the scene to load.options
(optional): An object containing optional parameters.additive
(default: true): Whether the scene should be loaded additively.enabled
(default: true): Whether the scene should be loaded as enabled or disabled (hidden).parent
(default: null): If not null, the loaded scene will be placed under this Scene Object.onProgress
(default: null): A callback function called during loading with the progress percentage (0-1).loadingScene
(default: null): The name of a scene to load during the background loading process.onComplete
(default: null): A callback function called when loading is completed, passed the loaded scene object.onFailure
(default: null): A callback function called if loading fails, passed an error message.
Returns:
A Promise that resolves with the LoadedScene object when loading is complete.
registerScene(registryItem: SceneRegistryItem, override?: boolean): SceneRegistryItem | undefined
Registers a new scene registry item, overriding existing item if override is true. Returns the registered item or undefined on failure.
unregisterScene(sceneName: string): void
Unregisters a scene registry item given a scene name. Throws error if not found.
findSceneByPrefab(prefab: ObjectPrefab): SceneRegistryItem | undefined
Finds a registry item for a given prefab asset. Returns item or undefined if not found.
findScenePrefabByName(sceneName: string): SceneRegistryItem | null
Finds a registry item by name. Returns item or null if not found.
getCurrentScene(requester: SceneObject): {myScene: LoadedScene, climbCount: number}
Gets the current parent scene of a given scene object requester by climbing its hierarchy.
unloadSceneByName(registryName: string): void
Unloads all instances of a scene given its registry name.
unloadScenes(scenes: LoadedScene[], onUnloadCompleteCallbacks?: Function[]): void
Unloads an array of scenes, optionally accepting callbacks per scene.
unloadScene(scene: LoadedScene, onUnloadComplete?: Function): void
Unloads a single scene, optionally accepting a callback when completed.
isLoaded(sceneName: string): LoadedScene[] | false
Checks if a scene is loaded by name. Returns an array of LoadedScene or false.
dontDestroyOnUnload(sceneObject: SceneObject): void
Prevents a scene object from being destroyed when its parent scene unloads.
Object Types
These are object types being used extensively by Scene Manager, if you plan to interface Scene Manager by scripting, you likely will need to deal with these object types.
SceneRegistryItem
Holds information about a registered scene - its name, asset source, and type.
sceneName
:string
, readonly, the name of the scenesceneAsset
:ObjectPrefab | RemoteReferenceAsset
, readonly, the prefab or remote asset for the scenetype
:"Asset.ObjectPrefab" | "Asset.RemoteReferenceAsset"
, readonly, the type of assetobjectPrefab
:ObjectPrefab | undefined
, package access, cached prefab if type is prefab
LoadedScene
Represents a scene that has been loaded, holds metadata like the time loaded, root object, etc.
manager
:SceneManager
, readonly, the SceneManager that loaded thisloadedTime
:number
, readonly, timestamp when loadedsceneRoot
:SceneObject
, readonly, root object of loaded scenesource
:SceneRegistryItem
, readonly, registry sourceisAdditive
:boolean
, readonly, if loaded additivelystate
:string
, package access, current state