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.

DestroyWhenStateAuthorityLeaves

Shared Mode Only Indicates if this NetworkObject will automatically be despawned when the StateAuthority Player leaves the game.

Back To Top

HasStateAuthority Property

The HasStateAuthority property is valid in both Shared and Server/Client modes, and will return true if: - Server/Client Mode; Runner.IsServer is true. - Shared Mode; StateAuthority == Runner.LocalPlayer.

Use this property in scripts to determine if this is the authoritative instance of this NetworkObject.

Back To Top

StateAuthority Property

The State Authority indicates which PlayerRef's peer is the final authority on the NetworkObject's state (Networked Properties), and its Networked Property values are replicated to other clients as Tick Snapshots.

NOTE: The StateAuthority property is only applicable to Shared Mode. In Server/Client Mode this value will always be PlayerRef.None, as the Server/Host peer will always act as State Authority.

Back To Top

Changing State Authority

In Server/Client Mode: State Authority always belongs to the Host/Server and cannot be transfered. StateAuthority will always be PlayerRef.None.

In Shared Mode: Player's have State Authority over NetworkObjects (the Photon Shared Server MANAGES State Authority of NetworkObjects, but does not HAVE State Authority over those objects).

Object.RequestStateAuthority() can be called on a client to assign its PlayerRef as the State Authority for the NetworkObject. The Photon Shared Server will only grant the request if; - The Object has AllowStateAuthorityOverride enabled; or, - The Object has no current State Authority.

If AllowStateAuthorityOverride is NOT enabled and there is already an assigned State Authority, the request will be ignored. The current State Authority Player must first call Object.ReleaseStateAuthority() on its client to free the Object.

Back To Top

AllowStateAuthorityOverride

Only applicable to Shared Mode. Indicates if the StateAuthority can be acquired by a Player when another player currently is the State Authority. If false, the current State Authority must first call ReleaseStateAuthority() or disconnect. For most use cases you will want to leave AllowStateAuthorityOverride enabled for Prefabs and Scene Objects.

This property must be set before spawning, as it cannot be changed after spawn.

Back To Top

HasInputAuthority Property

The HasInputAuthority property will return true if the Runner.LocalPlayer == Object.InputAuthority. Use this in scripts to test if the NetworkRunner.LocalPlayer is the Input Authority for this NetworkObject.

NOTE: Input Authority and Fusion's INetworkInput handling are primarily meant for Server/Client Mode, as they are fundamental to client prediction and resimulation. In Shared Mode however, user inputs are consumed immediately by the State Authority - making the INetworkStruct input system non-essential. You may however still wish to use the Fusion input system with Shared Mode if you are considering switching to Server/Client Mode in the future, and want to avoid refactoring later.

Back To Top

InputAuthority Property

The InputAuthority property indicates which PlayerRef's input data (INetworkInput) is returned when GetInput() is called in any FixedUpdateNetwork on this NetworkObject. Player Input is only available to the client with Input Authority, and to the State Authority. All other clients (Proxies) will return false when GetInput() is called.

Changing Input Authority

In Shared Mode: INetworkInput handling is optional in Shared Mode. If used however, only the current StateAuthority may change the InputAuthority, and can do so using the Object.AssignInputAuthority() method.

Input Authority should match State Authority or be PlayerRef.None. Input Authority is not automatically changed with StateAuthority changes, so be sure to change InputAuthority as needed in these cases.

public class StateAuthChangeExample : NetworkBehaviour, IStateAuthorityChanged
{
  void IStateAuthorityChanged.StateAuthorityChanged() {
    // If this object is using Fusion Inputs, the new State Authority
    // should acquire Input Authority when it gets State Authority.
    if (Object.HasStateAuthority) {
      Object.AssignInputAuthority(Object.StateAuthority.PlayerId);
    }
  }
}

In Server/Client Mode: The InputAuthority PlayerRef can only be changed on the Server with the Object.AssignInputAuthority() method.

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 Properties

Internally Fusion stores the entire networked state for each tick as a single memory buffer, called a Snapshot. Networked Properties define which variables in a NetworkedBehaviour are part of that networked state.

To define a Networked Property, use the [Networked] attribute. Fusion will automatically connect these tagged properties to 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.

This direct property access to the state buffer means that whenever a change occurs, the state 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

Allowed Types

  • Primitives
    • byte, sbyte
    • Int16, Int32, Int64
    • UInt16, UInt32, UInt64
    • float
    • double
    • float
    • double
    • bool (convereted to int)
  • Strings with a maximum Length set using the [Capacity] attribute (defaults to 16)
  • Unity struct types (defined in ILWeaver.cs)
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • System.Guid
  • User Defined INetworkStructs
  • Fusion Defined INetworkStructs
    • NetworkString<IFixedStorage>
    • NetworkBool
    • Ptr
    • Angle
    • BitSet64, BitSet128, BitSet192, BitSet256
    • PlayerRefSet
    • NetworkId
    • NetworkButtons
    • NetworkRNG
    • NetworkObjectGuid
    • NetworkPrefabRef
    • NetworkObjectHeader
    • NetworkPrefabId
    • SceneRef
    • TickTimer
    • IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
  • Fusion Types
    • NetworkObject (serialized as NetworkId)
    • NetworkBehaviour (serialized as NetworkId and the NetworkBehaviour index)
    • PlayerRef (serialized as PlayerRef.PlayerId)
  • NetworkArray<T> with a maximum Length set using the [Capacity] attribute (defaults to 1)
  • NetworkDictionary<K, V> with a maximum Count set using the [Capacity]
  • NetworkLinkedList<T> with a maximum Count set using the [Capacity] attribute.

Back To Top

Accuracy Attribute

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; }
}

Back To Top

Capacity Attribute

[Capacity] is used to define the maximum size of NetworkArray<T>, NetworkDictionary<K, V>, NetworkLinkedList<T> and strings.

public class MyNetworkBehaviour : NetworkedBehaviour 
{
  [Networked, Capacity(14)] 
  string MyString { get; set; }

  [Networked, 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