This document is about: FUSION 1
SWITCH TO

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

Interest Management

Overview

Interest Management is a set of data culling features, which restrict specific networked element updates from the server to specific clients/players. This culling is useful for reduction of network traffic, as well as restricting player access to data (such as team only information).

There are two main data culling mechanisms:

  • Object Interest: Restricts NetworkObject updates from server to specific PlayerRefs.
  • Interest Groups: Restricts specific Networked Property updates from server, on a per PlayerRef / per NetworkObject basis.
Interest Management is only available for the Eventual Consistency replication mode.
EventualConsistency and ObjectInterest enabled in NetworkProjectConfig
Eventual Consistency and Object Interest enabled in Network Project Config.

Object Interest

Object Interest determines which players will receive which NetworkObject updates (Networked Properties and RPCs) from the server.

The NetworkObject.ObjectInterest setting controls how Player interest for that object is determined. There are three mode options:

  • Area Of Interest: Only players with an AOI region which overlaps this object's AoiPositionSource in 3d space will be interested in this object.
  • All Players: All players receive updates for this object.
  • Explicit Players: Only players explicitly flagged will be interested in this object.
NetworkObject ObjectInterest Options
Object Interest Options

Area Of Interest

The server will use each player’s Area Of Interest (AOI) regions to determine if this NetworkObject is of interest to that player. Player AOI regions are specified by calling the Runner.AddPlayerAreaOfInterest() method.

These regions only apply for one tick, and need to be reapplied every tick in FixedUpdateNetwork. Players may have multiple regions (for example if the player is operating a remote camera). If this NetworkObject is inside one or more of a player’s AOI regions, that player will be interested and receive server updates for this NetworkObject from the server.

AoiPositionSource indicates which NetworkAreaOfInterestBehaviour derived component will be used by the game server to determine the NetworkObject's position in world space. If null, then the NetworkObject will search for a NetworkAreaOfInterestBehaviour at runtime.

Fusion's components which derive from NetworkAreaOfInterestBehaviour include:

  • NetworkPositionRotation
  • NetworkTransform
  • NetworkRigidbody
  • NetworkRigidbody2D
  • NetworkCharacterControllerPrototype
  • The Advanced KCC Add-on

C#

public class SetAreaOfInterest : NetworkBehaviour
{
  public float Extents = 32f;

  public override void FixedUpdateNetwork()
  {
    if (Runner.IsServer)
    {
      var controller = Object.InputAuthority;
      // Set the controlling players area of interest region around this object
      if (controller)
      {
        Runner.AddPlayerAreaOfInterest(controller, transform.position, Extents);
      }
    }
  }
}

NOTE: Object.SetPlayerAlwaysInterested() or Runner.SetPlayerAlwaysInterested() can be used in addition to AOI to force player interest in objects, even if they are outside of their AOI range.

NOTE: Currently AOI ranges are extents, and define a bounding box in world space on the X and Z axis. Y is ignored by AOI queries.

All Players

This NetworkObject is always of interest to all players. This effectively disables Object culling for this NetworkObject, and all players will receive server updates for this NetworkObject.

Explicit Players

This NetworkObject is not of interest to any player, UNLESS player interest is specifically added with Runner.SetPlayerAlwaysInterested(). Only players with explicit interest will receive server updates for this NetworkObject.

C#

public class MakeAlwaysInterested : NetworkBehaviour, IPlayerJoined
{
  void IPlayerJoined.PlayerJoined(PlayerRef player)
  {
    if (Runner.IsServer)
    {
      Object.SetPlayerAlwaysInterested(player, true);
      // or
      // Runner.SetPlayerAlwaysInterested(player, Object, true);
    }
  }
}

RPCs and Object Interest

Object Interest will also affect delivery of any non-static RPCs, as these are bound to an instance of a NetworkObject. The RpcInvokeInfo return value may be used on the server to detect and handle failures to send due to a player not having interest in the NetworkObject the RPC is attached to.

C#

[Rpc]
public RpcInvokeInfo RpcFoo()
{
  return default;
}

public override void FixedUpdateNetwork()
{
  if (Object.HasStateAuthority)
  {
    var info = RpcFoo();
    int culledCount = info.SendResult.CulledReceivers.Length;
    if (culledCount > 0)
    {
      //Handling for a target peer being culled from send
      Debug.LogWarning($"{culledCount} receivers culled, possibly due to no Object Interest.");
    }
  }
}

Interest Groups

Interest Groups can be used to restrict Networked Property updates to only specific players.

Networked Properties can be assigned to named Interest Groups, and the server will only send updates for these properties to players who have interest in that named Interest Group for this NetworkObject (player Interest Group assignment is per NetworkObject, and is not global).

Note: If a NetworkObject is not receiving updates due to Object Interest, then no member data will be updated either, regardless of Interest Groups.

Adding and Removing Player Interest in Groups

Network Properties which are assigned Interest Groups, are by default not replicated to players. There are two ways to assign Player interest in a NetworkObject's Interest Groups.

Explicitly Setting Player Interest

Player interest in groups is added and removed on a per NetworkObject basis, using the Object.SetInterestGroup() or Runner.SetInterestGroup() methods.

C#


using Fusion;
using UnityEngine;

public class PropertyGroupsSample : NetworkBehaviour, IPlayerJoined
{
  // This Networked Property is assigned to the group 'EvenOnly'
  // Only players with interest in 'EvenOnly' get property updates
  [Networked(group: "EvenOnly")]
  Color SecretColor { get; set; }

  public override void Spawned()
  {
    // Apply interest in this NetworkObject for existing players
    foreach (var player in Runner.ActivePlayers) {
      Object.SetInterestGroup(player, "EvenOnly", player % 2 == 0);
    }
  }

  void IPlayerJoined.PlayerJoined(PlayerRef player)
  {
    if (Runner.IsServer) {
      // Apply interest in this NetworkObject for any players who join late.
      // Only even numbered Players will be included in the group.
      Object.SetInterestGroup(player, "EvenOnly", player % 2 == 0);

      // This can alternatively be called directly with the runner (same meaning)
      //Runner.SetInterestGroup(Object, player, "EvenOnly", player % 2 == 0);
    }
  }

  public override void FixedUpdateNetwork()
  {
    if (Object.HasStateAuthority)
    {
      SecretColor = Color.HSVToRGB((Runner.Tick / 20f) % 1f, 1f, 1f);
    }
  }

  public override void Render()
  {
    GetComponent<Renderer>().material.color = SecretColor;
  }
}

Default Interest Groups

All joining players will start with explicit interest in these groups for this NetworkObject. For any groups not in this list, players must explicitly be assigned group interest for this NetworkObject using the method Object.SetInterestGroup() or Runner.SetInterestGroup() (as shown in the example above).

Back to top