Scene Loading
Overview
Fusion internally contains no Unity Scene handling implementations, but it does provide an INetworkSceneManager
interface,
where you can define how Fusion responds to various Scene related events - such as scene changes. An implementation of INetworkSceneManager
hereon will be referred to as a Scene Manager.
An implementation of INetworkSceneManager
needs to be assigned in the NetworkRunner.StartGame()
method via the StartGameArgs.SceneManager
field.
If no implementation is provided (null), Fusion will create an instance of the NetworkSceneManagerDummy
class and log an error communicating that it will not be able to link scene objects.
An default implementation named NetworkSceneManagerDefault
comes with Fusion which can:
- Load and Unload scenes.
- Supports regular scene loading and scene loading via addressables.
- Can reload currently active scenes.
- Loads up to 8 scenes simultaneously using additive scene loading.
- Supports multi-peer scene loading with correct PhysicsScene associations for each Runner.
Load and Unload scenes
Important: Both LoadScene()
and UnloadScene()
are only allowed to be called on the Server/Host or Master Client. (This is enforced by the default scene manager implementation. Custom implementations must also enforce this)
To load a scene, simply call NetworkRunner.LoadScene()
passing the SceneRef
of the scene and the LoadSceneParameters
. Keep in mind that loading with single load mode will unload all previous scenes, while with additive scene loading previous scenes remain loaded.
C#
// Loading 3 scenes in additive mode.
if (Runner.IsSceneAuthority) {
Runner.LoadScene(SceneRef.FromIndex(1), LoadSceneMode.Additive);
Runner.LoadScene(SceneRef.FromIndex(2), LoadSceneMode.Additive);
Runner.LoadScene(SceneRef.FromIndex(3), LoadSceneMode.Additive);
}
The index used to create the SceneRef
is the index of the scene in the Unity build. To get the index of the current scene you can use SceneManager.GetActiveScene().buildIndex
. For other scenes the index can be found by scene path using SceneUtility.GetBuildIndexByScenePath
. For instance to load the Scene that is stored at Assets/Scenes/GameScene.unity
the following code is used:
C#
Runner.LoadScene(SceneRef.FromIndex(SceneUtility.GetBuildIndexByScenePath("Assets/Scenes/GameScene.unity")), LoadSceneMode.Additive);
To unload a scene, simply call NetworkRunner.UnloadScene()
passing the SceneRef
of the scene to be unloaded.
C#
// Unloading scene 1.
if (Runner.IsSceneAuthority) {
Runner.UnloadScene(SceneRef.FromIndex(1));
}
It is also possible to reload scenes by unloading and loading them again in sequence.
The NetworkSceneManagerDefault
implementation maintain a Version
field that works as a counter, increasing every time a scene is loaded or unloaded,
this value is used to register the load ID of the scene object to differentiate between the last loaded scene and the new loaded one, even though they're
the same scene.
C#
// Reloading scene 2.
if (Runner.IsSceneAuthority) {
Runner.UnloadScene(SceneRef.FromIndex(2));
Runner.LoadScene(SceneRef.FromIndex(2), LoadSceneMode.Additive);
}
SceneRef
s can be created from a scene index with SceneRef.FromIndex(int index)
or from a path, mostly used to create references to addressables scenes, with SceneRef.FromPath(string path)
.
Creating a custom Network Manager
NetworkSceneInfo
Represents user-controlled active scene information, it can store up to 8 active scenes and allows for duplicates.
It is a great starting point to creating a custom implementation. This network struct is what the NetworkRunner
will network in order to properly sync scene loading. Whenever the scene authority (Host/Server or Master Client) changes the scene info,
OnSceneInfoChanged()
will be called on the INetworkSceneManager
instance registered on the NetworkRunner
.
INetworkSceneManager
Provide a custom implementation of this interface on StartGameArgs
to have full control on how scene loading is handled.
Keep in mind that this implementation needs to call the Fusion scene loading callbacks Runner.InvokeSceneLoadStart(sceneRef)
and
Runner.InvokeSceneLoadDone(SceneLoadDoneArgs)
. Take a look at the NetworkSceneManagerDefault
implementation to see the default behaviour.
When implementing a custom scene manager, the interface will provide the following:
void Initialize(NetworkRunner runner)
: Called when the runner initializes itself. Use it to store theNetworkRunner
reference and do any warmup necessary.void Shutdown()
: Called when the runner shutdown. Use it to release any references and stop any pending actions.bool IsBusy
: Use this property to tell when the scene manager is busy loading a scene or doing anything else that theNetworkRunner
or other systems on your game may need to be aware of.Scene MainRunnerScene
: Use this property to tell which scene is the main scene of aNetworkRunner
. This is mainly used for multi-peer support. (Check the default implementation for more information)bool TryGetPhysicsScene2D(out PhysicsScene2D scene2D)
: Set the 2D physics scene on the out parameter, return the result of the operation.bool TryGetPhysicsScene3D(out PhysicsScene scene3D)
: Set the 3D physics scene on the out parameter, return the result of the operation.void MakeDontDestroyOnLoad(GameObject obj)
: Make an object not be destroyed on load. Used for multi-peer support. (Check the default implementation for more information)void MoveToRunnerScene(GameObject obj)
: Move the passed object to the scene related with theNetworkRunner
. This is only used for multi-peer support. (Check the default implementation for more information)bool IsRunnerScene(Scene scene)
: Return if this scene is related with theNetworkRunner
. Used for multi-peer support. (Check the default implementation for more information)NetworkSceneAsyncOp LoadScene(SceneRef sceneRef, LoadSceneParameters parameters)
: Use this method to load a new scene with the received parameters. The way that the scene will be loaded is entirely up to the developer, the only needed step is to register the newly loadedNetworkObjects
withNetworkRunner.RegisterSceneObjects(SceneRef scene, NetworkObject[] objects, byte loadId = 0)
. The additional loadId parameter is passed to ensure each scene load yields unique type ids for scene objects.NetworkSceneAsyncOp UnloadScene(SceneRef sceneRef)
: Use this method to unload a scene.void OnSceneInfoChanged()
: Called when theINetworkSceneInfo
on theNetworRunner
is changed. Use this method to react and trigger scene loading on clients since only the scene authority should be able to callLoadScene
.SceneRef GetSceneRef(string sceneName)
: Use this method to return aSceneRef
based on the provided scene name.