This document is about: FUSION 2
SWITCH TO

Spawning

Introduction

NetworkObjects cannot be instantiated with the regular GameObject.Instantiate functions instead they have to be spawned.

To spawn a NetworkObject at runtime use the Runner.Spawn() method. Scene objects do not need to be spawned they are automatically spawned when the scene is loaded.

The NetworkObject is used by Fusion to assign a network-wide unique identifier so all clients can agree on which instance is which and correctly synchronize each networked object's state. The Runner.Spawn() method tells Fusion when and how to add a new object instance to the collective network state.

IMPORTANT!

Do NOT use Unity's built in GameObject.Instantiate() method for networked object , this will just create a local game object which is completely detached from the Fusion simulation loop with a broken network state.

Runner.Spawn

The Runner.Spawn() method on the Fusion NetworkRunner instance mimics the GameObject.Instantiate() method in Unity. The parameters that can be provided to the method are:

  1. a prefab of type NetworkObject.
  2. a position
  3. a rotation
  4. a PlayerRef to identify the client with input authority over the object. (Only relevant for Host/Server Mode)
  5. a delegate of type NetworkRunner.OnBeforeSpawned to run before replicating the object on the other instances

Only the prefab is a mandatory parameter, all others are optional.

Note: if you pass a position and/or rotation to the Spawn method it will only affect the object's transform on the peer that spawns it. To see this position and rotation reflected on other peers you can attach a NetworkTransform, any other component which inherits from NetworkTRSP or a fully custom component which synchronizes the transform data.

C#

var obj = Runner.Spawn(prefab, Vector3.zero, Quaternion.identity, Runner.LocalPlayer, MyOnBeforeSpawnDelegate);

Although any client can call Runner.Spawn(), the results will differ depending on the network topology.

  • In Host and Server Mode only the Host/Server can spawn NetworkObjects. Clients need to send a request to the Host/Server (such as an RPC) to request a spawn instead.
  • In Shared Mode any client can spawn a NetworkObject. Spawning a NetworkObject automatically assigns StateAuthority over it to the client.

Input Authority

The input authority is assigned to a particular client by passing in their PlayerRef to the method; this is optional. The client to whom input authority was given will be able to provide input data for the object and (in addition to the Host or Server) is allowed to query that input structure in GetInput().

If the object does not require input or no client has input authority over it, null can be passed instead.

OnBeforeSpawned

The NetworkRunner.OnBeforeSpawned parameter can take a method or lambda expression matching the delegate signature.

C#

public delegate void OnBeforeSpawned(NetworkRunner runner, NetworkObject obj);

This delegate is invoked after the object is created but before it gets synchronized across all instances. This allows the caller to perform additional custom initialization of the object before any other part of the system is able to access it. This is a good place to initialize custom network properties.

C#

private void MySpawnFunction(){
    Runner.Spawn(
        _objPrefab, 
        Vector3.zero, 
        Quaternion.identity, 
        inputAuthority: null, 
        InitializeObjBeforeSpawn,
        predictionKey: null
        );
}

private void InitializeObjBeforeSpawn(NetworkRunner runner, NetworkObject obj)
{
    var objSB = obj.GetComponent<ObjSimulationBehaviour>();
    objSB.InitializeObjSettings(_currentExplosionForce);
}

It is also possible to use a lambda expression to have the possibility to pass more parameters.

C#

private void MySpawnFunction(){
  Runner.Spawn(
    _objPrefab,
    Vector3.zero,
    Quaternion.identity,
    inputAuthority: null,
    (Runner, NO) => NO.GetComponent<MyCustomBehaviour>().Init(myInt, myParameter)
    predictionKey: null
    );
}

Spawned

ISpawned.Spawned() is called immediately after the NetworkRunner attaches a NetworkObject (either as a result of a NetworkRunner.Spawn() call, or loading a Scene which contained a NetworkObject). The Spawned() callback can be considered Fusion's alternative to Awake(), and is called AFTER the object has been attached and is valid.

NetworkBehaviour implements the ISpawned interface with an empty virtual Spawned() method. To implement Spawned() for a custom NetworkBehaviour, simply override Spawned().

Any Networked Property values changes made on the State Authority in Spawned() will be the initial values for all spawned instances of that NetworkObject on all other peers. HOWEVER, remote peers may not always spawn objects on the same tick as the State Authority (due to Area of Interest, Interest Management, late joining, and Prioritization). When a NetworkObject spawns remotely on a later tick than the State Authority, it will spawn with the values that the State Authority had for that later tick.

  • For spawns on a peer with State Authority, Spawned() is called immediately after Runner.Spawn().
  • For non-State Authority peers, The NetworkObject is spawned when the NetworkRunner receives a network state for an NetworkObject that does not exist locally.

If a NetworkObject should be initialized at prior to being attached to the NetworkRunner, use a pre-spawn OnBeforeSpawned callback supplied to Runner.Spawn().

IAfterSpawned

IAfterSpawned.AfterSpawned() is called after a batch of NetworkObjects have spawned and have all ISpawned.Spawned() callbacks have finished. This can be thought of as Fusion's alternative to Start(). Use this callback when a NetworkBehaviour needs to get or set values in another NetworkBehaviour after spawning, without concerns about execution order.

Despawn

To remove a network object, the peer with State Authority over the object may call Runner.Despawn().

Despawned

Similar to how Runner.Spawn() triggers the Spawned() method call for classes implementing ISpawned such as NetworkBehaviour, Despawn() will result in the Despawned() method to be called for classes implementing IDespawned.

Back to top