Scene Management

A Spatial space consists of only a single Unity scene. You cannot load multiple scenes or unload scenes dynamically at runtime.

If you're used to creating several scenes for different levels, or even reloading the same scene to reset the game, you’ll have to design around this limitation.

Strategies

Here are some strategies for building around this limitation, which are also used by the Spatial team internally.

Create levels as prefabs and instantiate/destroy them

Instead of building "levels" inside of scenes, you should instead build them inside of prefabs and Instantiate / Destroy where you would normally Load / Unload a scene.

For Buddy Blitz we used this strategy: the levels were loaded and unloaded via scripting. During development, we actually had different scenes with the prefab we wanted to test.

Creating levels as prefabs for Buddy BlitzBuddy Blitz different scenes

Using this strategy you will be able to subdivide your content and load/unload it accordingly.

Create a SceneManager to handle top level “scenes”

Group your “scenes” as a top level game objects and create a SceneManager script that handles loading/unloading. This is similar to the first strategy, but you could potentially have everything on the scene. In the following sample, the Scene script was just created to recreate the scene object when the Restart() function is called.

Create a SceneManager to handle top level scenesSceneManager configuration

/// <summary>
/// Spatial: Class that handles scene restarts. Spatial only supports one scene, so we create a 'prefab' out of the entire scene
/// we want to reload and then instantiate it when we want to restart the scene.
/// </summary>
[DefaultExecutionOrder (-1000)]
public class CustomSceneManager: MonoBehaviour
{
public GameObject activeScene;
private GameObject _sceneObjectPrefab;
private static CustomSceneManager _instance;

private void Awake()
{
if (_instance != null)
{
Destroy(this);
return;
}

_instance = this;
activeScene.SetActive(false);

// Save a copy of the scene.object
_sceneObjectPrefab = Instantiate (activeScene);

activeScene.SetActive(true);
}

public static void Restart()
{
if (_instance == null)
{
Debug.LogError("Scene instance is null");
return;
}

Destroy(_instance.activeScene);
_instance.activeScene = Instantiate(_instance._sceneObjectPrefab);
_instance.activeScene.SetActive(true);
}
}

/// <summary>
/// Spatial: Class that handles scene restarts. Spatial only supports one scene, so we create a 'prefab' out of the entire scene
/// we want to reload and then instantiate it when we want to restart the scene.
/// </summary>
[DefaultExecutionOrder (-1000)]
public class CustomSceneManager: MonoBehaviour
{
public GameObject activeScene;
private GameObject _sceneObjectPrefab;
private static CustomSceneManager _instance;

private void Awake()
{
if (_instance != null)
{
Destroy(this);
return;
}

_instance = this;
activeScene.SetActive(false);

// Save a copy of the scene.object
_sceneObjectPrefab = Instantiate (activeScene);

activeScene.SetActive(true);
}

public static void Restart()
{
if (_instance == null)
{
Debug.LogError("Scene instance is null");
return;
}

Destroy(_instance.activeScene);
_instance.activeScene = Instantiate(_instance._sceneObjectPrefab);
_instance.activeScene.SetActive(true);
}
}

To use this class, you'd use it with CustomSceneManager.Restart() in case you want to restart the current 'scene'. This will internally destroy the game object and recreate it based on the scene object prefab that was stored on Awake.