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

Network Behaviour

Overview

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

NetworkBehaviour functions similarly to SimulationBehaviour with the addition that it can carry a synchronized state. This is the reason why it has to have an associated NetworkObject.

Back To Top

Overridable Methods

A NetworkObject has a number of additional life-cycle methods, all of which can be overridden when implementing 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

Networked State

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.

Networked Properties

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

The following types are supported by Fusion and can be [Networked]:

  • Primitives
    • byte, sbyte
    • short, int, long
    • ushort, uint, ulong
    • float, double
    • bool (converted 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
  • Enums
  • 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)
  • Network Collections

Back To Top

Networking Fusion Object Types

NetworkObject and NetworkBehaviour references can be Networked Properties of a NetworkBehaviour. (Note: These are not valid in INetworkStruct).

Internally, these Networked NetworkObject and NetworkBehaviour references are converted to NetworkId and NetworkBehaviourId values.

The ILWeaver generated Set method converts (wraps) the reference to its Id, and that Id is what is networked.

The ILWeaver generated Get method converts (unwraps) the Id to a reference using the Runner.TryGetObject() and Runner.TryGetBehaviour() methods.

[Networked] public NetworkObject MyNetworkObject { get; set; }
[Networked] public CustomNetworkBehaviour MyNetworkBehaviour { get; set; }

While convenient, this automation does mean that:

  • an explicit null value, and;
  • a failure to unwrap

will both return a null value for Get - with no distinction between the two.

An alternative to using NetworkObject and NetworkBehaviour for properties, is to instead use NetworkId and NetworkBehaviourId values.

Explicitly syncing these references by Id, you can detect if a null value:

  • indicates an explicit null (0), or;
  • indicates an object (a value > 0), but that Object just does not exist locally currently (failed to unwrap).

Back To Top

NetworkId Usage Example

using Fusion;

public class SyncNetworkObjectExample : NetworkBehaviour
{
  // NetworkId is backed by one int value.
  // A zero value (default) represents null.
  [Networked] public NetworkId SyncedNetworkObjectId { get; set; }

  private void SetObject(NetworkObject netObj)
  {
    SyncedNetworkObjectId = netObj != null ? netObj.Id : default;
  }

  bool TryResolve(out NetworkObject no)
  {
    // A default (0) value indicates an explicit null value.
    // Return true to represent successfully resolving this to null.
    if (SyncedNetworkObjectId == default)
    {
      no = null;
      return true;
    }

    // Find the object using the non-null id value.
    // Return true if the lookup was successful.
    // Return false and null if the NetworkObject could not be found on the local Runner.
    bool found = Runner.TryFindObject(SyncedNetworkObjectId, out var obj);
    no = obj;
    return found;
  }
}

Back To Top

NetworkBehaviourId Usage Example

using Fusion;

public class SyncNetworkBehaviourExample : NetworkBehaviour
{
  // NetworkId is backed by two int values.
  // Object = NetworkObject.Id (value of 0 represents null/Invalid).
  // Behaviour = NetworkBehaviour index in GameObject hierarchy.
  [Networked] public NetworkBehaviourId SyncedNetworkBehaviourId { get; set; }

  private void SetBehaviour(NetworkBehaviour nb)
  {
    SyncedNetworkBehaviourId = nb != null ? nb.Id : default;
  }

  bool TryResolve(out NetworkBehaviour no)
  {
    // A default (0) value indicates an explicit null value.
    // Return true to represent successfully resolving this to null.
    if (SyncedNetworkBehaviourId == default)
    {
      no = null;
      return true;
    }

    // Find the NetworkBehaviour using the non-default id value.
    // Return true if the lookup was successful.
    // Return false and null if the NetworkObject could not be found on the local Runner.
    bool found = Runner.TryFindBehaviour(SyncedNetworkBehaviourId, out var obj);
    no = obj;
    return found;
  }
}

Back To Top

Setting Default Values

It is possible to set default values for [Networked] properties.

Back To Top

Common Types

For most common types a simple assignment is sufficient.

public class PlayerBehaviour : NetworkedBehaviour
{
  [Networked] public float Health { get; set; } = 100;
  [Networked] public NetworkObject DefaultNetworkObject { get; set; } = GameObject.FindGameObjectWithTag("Foo").GetComponent<NetworkObject>();
}

Back To Top

Collections

Network Collections such as NetworkArray<T> , NetworkDictionary<K, V> , NetworkLinkedList<T> and NetworkString<_size> require a special syntax. Please refer to the page of the same name for more information.

Back To Top

Ref And Ptr

It is possible to set default values for references and pointers by using the appropriate constructors.

[Networked] public ref Byte Prop => ref MakeRef<Byte>(123);
[Networked] public Byte* Prop => MakePtr<Byte>(123);

Back To Top

Additional Attributes

The [Networked] attribute can be combined with several other attributes to define more specifically how the network state is handled.

Accuracy

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

[Capacity] is used to define the maximum size of NetworkArray, NetworkDictionary, NetworkLinkedList, NetworkString and strings.

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

  [Networked, Capacity(8)]
  NetworkArray<byte> MyArray { get; }
}

For more information on the handling of network collection, please refer to the Network Collections page.

Back To Top

OnChanged

Game code can be triggered when a change is detected in a networked property between two render frames. To write reactive code, use the (OnChanged) parameter on the [Networked] attribute.

public class Powerup : NetworkBehaviour
{
    [Networked(OnChanged = nameof(OnXyzChanged))] public TypeOfProperty Xyz { get; set; }

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

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

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

  • OnChangedTargets (default All): Choose between Proxies, InputAuthority and StateAuthority to limit which peers will have the callback invoked. If you do not specify a target, all peers will have the callback invoked.

Note that OnChanged callbacks are called when a change is detected between two Unity Update calls. I.e. these callbacks are not tick aligned and will only detect changes that occur between two render frames, and as such should never be used for gameplay logic. The primary use case for OnChange callbacks is to trigger visual or audio effects, specifically on proxies.

The Changed<T> parameter provides access to all properties of the behaviour both before and after the change - use LoadOld and LoadNew to toggle between the two:

private static void OnXyzChanged(Changed<Powerup> changed)
{
  var new_value = changed.Behaviour.Xyz;
  changed.LoadOld();
  var old_value = changed.Behaviour.Xyz;
}

Back To Top

Generics

It is possible to create templated classes deriving from NetworkBehaviour. These can even contain [Networked] properties.

// This is VALID
class ValidGenericClass_With_NonGenericProperty<T> : NetworkBehaviour {
    [Networked] public int Prop { get; set; }
}

However, it is NOT possible to have a generic [Networked] property of type <T>.

// This is INVALID
class InValidGenericClass_With_GenericProperty<T> : NetworkBehaviour {
    [Networked] public T Prop { get; set; }
}


To Document Top