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 specificPlayerRef
s. - Interest Groups: Restricts specific Networked Property updates from server, on a per
PlayerRef
/ perNetworkObject
basis.
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.
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: Add/Remove a
PlayerRef
's interest in a specific group for thisNetworkObject
. - Default Interest Groups: Automatically set ALL players as interested in specific groups for this
NetworkObject
.
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).