This page is a work in progress and could be pending updates.

Network Object

Introduction

The NetworkObject assigns a network identity to a GameObject so it can be shared across the network. Any GameObject that is seen by all players and is a dynamic part of the scene should carry a NetworkObject script.

Fusion offers two NetworkObject base classes for deriving custom network behaviours:

  • SimulationBehaviour for simulation related behaviours; and,
  • NetworkBehaviour for behaviours keeping or tracking a [Networked] state.

Back To Top

NetworkObject

A single NetworkObject script on the root node of a GameObject is sufficient to control the entire hierarchy. At runtime the NetworkObject will find all SimulationBehaviours and NetworkBehaviours in its hierarchy.

If needed, NetworkObjects can be nested. In this case, the NetworkObject will not search into nested children and let child NetworkObjects track all SimulationBehaviours and NetworkBehaviours below it. A typical usecase would be a two player controlled tank made of a chassis and a turret where the driver controls the chassis' direction (movement) and the gunner controls the turret (shooting).

Back To Top

Prefab / Object Table

In order for the Prefab parameter to make sense to Fusion (and to be sure that all clients agree on exactly which prefab that is), the prefab itself must be registered with Fusion. Under normal circumstances the Fusion toolset will automatically detect these prefabs and register them, but you can also manually trigger this detection by selecting the NetworkProjectConfig and pressing Rebuild Object Table in the Unity Inspector.

Back To Top

Instantiation / Spawn

The instantiation of NetworkObject prefabs requires two steps:

  1. At edit-time: ensure the clients have to have identical NetworkProjectConfig assets which agrees on the NetworkObject prefab identities. This is done by running Rebuild Object Table in the NetworkProjectConfig asset; and,
  2. At runtime: call Spawn() on the NetworkRunner with a NetworkObject prefab as the parameter.

IMPORTANT: Calling the generic Unity Instantiate() method will just create a broken local instance!

Back To Top

Destruction / Despawn

To destroy a NetworkObject, call Runner.Despawn() and pass the object as a parameter. This will destroy the object as well as all nested objects; to despawn only the top object, the nested objects need to be de-parented manually first.

Back To Top

Authority

A NetworkObject has two types of authority (aka ownership):

  • Input Authority; and,
  • State Authority.

Back To Top

Input Vs State

Input Authority allows to collect and send user input for that object. It will also enable the client to acquire that same input in FixedUpdateNetwork() to simulate and locally predict the future state of the object. State Authority enables reading and simulating the state based on the input, thus allowing the prediction and the true state to be mutated by the same code.

In other words, State Authority gives final control of the objects' state and directly dictates what goes into the delta snapshots sent to all other clients for synchronization. Eventually the state set by the client with State Authority will replace whatever a client with Input Authority predicted.

Back To Top

Assigning Authority

The game code can check the authority type a client has over a given NetworkObject via the HasInputAuthority and HasStateAuthority properties.

When a NetworkObject is spawned with Runner.Spawn(), the calling client may assign Input Authority to itself or any other client.

  • If the network mode is set to Client Authority, the client can also assume State Authority over the object.
  • If the network mode is set to dedicated server or client host, State Authority will always be assign there.

Back To Top

SimulationBehaviour

All SimulationBehaviours can access their associated NetworkObject via the Object property.

Simulation is Fusion's way of updating the network state. Any behaviours which are part of or affect the simulation state have to derive from SimulationBehaviour instead of MonoBehaviour.

For example, the LevelManager in the Tanks sample spawns powerups. Although powerups are NetworkObjects, the LevelManager only has to affect and know of the simulation state to execute its behaviour. Therefore, inheriting from SimulationBehaviour is the right approach.

public class LevelManager : SimulationBehaviour
{
    [SerializeField] private float _powerupDelay;
    [SerializeField] private NetworkObject _powerupPrefab;

    private TickTimer _powerupTimer;

    public override void FixedUpdateNetwork()
    {
        // All of the level management logic happens server-side, so bail if we're not the server.
        if (!Object.HasStateAuthority) return;

        // Only active duty of the LevelManager is to spawn powerups whenever the timer expires
        if (_powerupTimer.ExpiredOrNotRunning(Runner)) {
            // Reset timer, and check if there is a free spot to spawn a new powerup
            _powerupTimer = TickTimer.CreateFromSeconds(Runner,_powerupDelay);
            SpawnPoint spawnPoint = GetSpawnPoint(SpawnPoint.Type.Powerup);

            if (spawnPoint != null) {
                Debug.Log("Spawning Powerup");
                NetworkObject powerupobj = Runner.Spawn(_powerupPrefab, spawnPoint.transform.position, spawnPoint.transform.rotation, PlayerRef.None);
                powerupobj.GetComponent<Powerup>().Init();
            } else {
                Debug.Log("Not Spawning Powerup - no free spot");
            }
        }
    }    
}

If the behaviour requires access to [Networked] properties, it has to derive from NetworkBehaviour instead.

Back To Top

NetworkBehaviour

A NetworkBehaviour requires a NetworkObject on the same node or a parent node.

NetworkBehaviour is a SimulationBehaviour which can carry a synchronized state; this is the reason why it has to have an associated NetworkObject.

Back To Top

Networked State

Internally Fusion keeps a single memory buffer that represents the entire networked state for the current local tick. The state is exposed to game code by marking properties with the [Networked].

To define and serialize a network state value, add the [Networked] attribute in front of a property. Fusion will automatically handle the tagged properties with its own high performance data buffers and delta compression. The property setters and getters are compile-time replaced with custom code to eliminate memory allocation overhead and provide optimal performance.

public class PlayerBehaviour : NetworkedBehaviour {
  [Networked] public float Health { get; set; }
}

At compile-time Fusion will replace the empty get/set stubs with code that accesses the actual networked state data. The direct access eliminates the memory allocation overhead and provides optimal performance. DO NOT implement them manually.

The direct access to the buffer also means that whenever a change occurs, the properties reflects that change immediately.

To write logic affecting networked state, override and implement FixedUpdateNetwork().

public override void FixedUpdateNetwork() {
    Health += Runner.DeltaTime * HealthRegen;
}

Back To Top

Constraints

[Networked] properties have to comply with these contraints:

  • the property has to have an empty get/set pair;
  • it can only contain the following types:
    • primitive types (see below for a full list)
    • Unity types (see below for a full list)
    • structs which implement INetworkStruct and are defined at the top-level (i.e. cannot be nested in a class)
    • pointers to network structs
    • strings with a maximum length set using the [Capacity] attribute (defaults to 16)
    • NetworkObject
    • NetworkBehaviour subclasses
    • NetworkArray<T> with a maximum length set using the [Capacity] attribute (defaults to 1)
  • for boolean values use NetworkBool instead of bool - C# does not enforce a consistent size for bools across platforms so NetworkBool is used to properly serialize it as a single bit.

Available primitive types are:

  • byte, sbyte
  • Int16, Int32, Int64
  • UInt16, UInt32, UInt64
  • float
  • double

Available Unity types are:

  • Vector2, Vector3, Vector4
  • Quaternion
  • Matrix4x4
  • BoundingSphere
  • Bounds
  • Rect
  • Color
  • Vector2Int, Vector3Int
  • BoundsInt
  • RectInt
  • Color32

Back To Top

Attributes

It is possible to control the accuracy of individual numeric type properties by using the [Accuracy] attribute.

public class PlayerBehaviour : NetworkedBehaviour {
  [Networked, Accuracy(0.001)]
  public float Health { get; set; }
}

[Capacity] is used to define the maximum length of NetworkArrays and strings; setting their maximum length is required for Fusion to be able to network those types.

[Capacity(14)] string MyString { get; set; }
[Capacity(8)]  NetworkArray<byte> MyArray { get; }

Back To Top

React To OnChanged

Game code can to be triggered when a networked property is changed by Fusion. To write reactive code, use the (OnChanged) parameter in the [Networked] attribute.

public class Powerup : NetworkBehaviour{
    [Networked(OnChanged = nameof(OnTypeChanged))] public Type type { get; set; }

    // Has to be public static void
    public static void OnTypeChanged(Changed<Powerup> changed){
        changed.Behaviour.OnTypeChanged();
    }

    private void OnTypeChanged(){
        // Some logic reacting to the value change of the "type" property
    }
}

In addition to specifying the callback name, it is possible to control on which machines the callback is executed:

  • OnChangedLocal (default false): set to true to also have the event hook called on the machine that changed the property
  • OnChangedRemote (default true): set to false to only have the event hook called on the machine that changed the property.

Back To Top

Overridable Methods

A NetworkObject has a number of additional life-cycle methods, all of which can be overriden when implementating SimulationBehaviour and NetworkBehaviour.

Function Description
FixedUpdateNetwork() Fusion's fixed time step callback. Used for the core game logic.
Spawned() Post spawn callback.
Despawned(bool hasState) Called before the network object is despawned.
---
bool hasState: If the state of the behaviour is still accessible.
Render() Post simulation frame rendering callback. Runs after all simulations have finished. Use in place of Unity's Update when Fusion is handling Physics.

Back To Top

FixedUpdateNetwork

FixedUpdateNetwork() - abbreviated FUN()- is called when simulating the new state from one tick to the next. FixedUpdateNetwork() is called at fixed intervals; the time step of these intervals is defined in the NetworkProjectConfig asset under Simulation > Tick Rate. The time step can be accessed from any SimulationBehaviour and NetworkBehaviour via the Runner.DeltaTime property.

FixedUpdateNetwork() can be called multiple times for the same state transition to re-simulate the current predicted state based on updates (ground truth) received from the server. The re-simulation is transparent for [Networked] properties because Fusion will reset the network state before calling FixedUpdateNetwork() for re-simulation purposes.

IMPORTANT: Regular local non-networked state variables (e.g. class members) will not be reset and simply consider it an additional forward state progression.

To Document Top