Skip to main content

Object visibility

What Is NetworkObject Visibility?

Object (NetworkObject) visibility is a Netcode for GameObjects term used to describe whether a NetworkObject is visible to one or more clients as it pertains to a netcode/network perspective. When a NetworkObject is visible to a client, the server will assure the client has a spawned version (a clone) of the NetworkObject. This also means that all network traffic generated by the server for the visible NetworkObject will be sent to all clients that are aware (that is, it's "visible to the clients") of it. Likewise, when a NetworkObject is "hidden" (that is, not visible) from a client, then the client will despawn and destroy the NetworkObject if it was previously visible and no network traffic generated by the hidden NetworkObject will be received by the client(s) it's hidden from.

Using Visibility

One way to determine visibility is to assign a callback to NetworkObject.CheckObjectVisibility. This callback is invoked when new clients connect or just before the associated NetworkObject is spawned. Looking at the example below, we can see the callback includes a client identifier (clientId) value as a parameter which is used to determine whether the NetworkObject is visible to the client. If NetworkObject.CheckObjectVisibility isn't assigned, then Netcode for GameObjects assumes it's visible to all clients.

CheckObjectVisibility Callback Example

public class VisibilityCheckExample : NetworkBehaviour
{
public bool ContinuallyCheckVisibility = true;
public float VisibilityDistance = 5.0f;

/// <summary>
/// This is automatically invoked when spawning the network prefab
/// relative to each client.
/// </summary>
/// <param name="clientId">client identifier to check</param>
/// <returns>true/false whether it is visible to the client or not</returns>
private bool CheckVisibility(ulong clientId)
{
// If not spawned, then always return false
if (!IsSpawned)
{
return false;
}

// We can do a simple distance check between the NetworkObject instance position and the client
return Vector3.Distance(NetworkManager.ConnectedClients[clientId].PlayerObject.transform.position, transform.position) <= VisibilityDistance;
}

public override void OnNetworkSpawn()
{
if (IsServer)
{
// The server handles visibility checks and should subscribe when spawned locally on the server-side.
NetworkObject.CheckObjectVisibility += CheckVisibility;
// If we want to continually update, we don't need to check every frame but should check at least once per tick
if (ContinuallyCheckVisibility)
{
NetworkManager.NetworkTickSystem.Tick += OnNetworkTick;
}
}
base.OnNetworkSpawn();
}

private void OnNetworkTick()
{
// If CheckObjectVisibility is enabled, check the distance to clients
// once per network tick.
foreach (var clientId in NetworkManager.ConnectedClientsIds)
{
var shouldBeVisibile = CheckVisibility(clientId);
var isVisibile = NetworkObject.IsNetworkVisibleTo(clientId);
if (shouldBeVisibile && !isVisibile)
{
// Note: This will invoke the CheckVisibility check again
NetworkObject.NetworkShow(clientId);
}
else if (!shouldBeVisibile && isVisibile)
{
NetworkObject.NetworkHide(clientId);
}
}
}

public override void OnNetworkDespawn()
{
if (IsServer)
{
NetworkObject.CheckObjectVisibility -= CheckVisibility;
NetworkManager.NetworkTickSystem.Tick -= OnNetworkTick;
}
base.OnNetworkDespawn();
}
}

Additional Visibility Methods and Properties:

The CheckObjectVisibility callback helps you determine if a NetworkObject is visible to a specific client when the NetworkObject is spawned. However, you might have the need to change a NetworkObject's visibility after it's spawned. To change the visibility of a NetworkObject that is already spawned, you can use the following methods:

Make a NetworkObject visible to a single client:

NetworkObject netObject = GetComponent<NetworkObject>();
netObject.NetworkShow(clientIdToShowTo);

Make a NetworkObject invisible/hidden from a single client:

NetworkObject netObject = GetComponent<NetworkObject>();
netObject.NetworkHide(clientIdToHideFrom);

Make several NetworkObjects visible to a single client (static method):

/// networkObjects is of type List<NetworkObject>
NetworkObject.NetworkShow(networkObjects, clientId);

Make several NetworkObjects invisible/hidden to a single client (static method):

/// networkObjects is of type List<NetworkObject>
NetworkObject.NetworkHide(networkObjects, clientId);

Spawn a NetworkObject with no observers (i.e. not visible to any clients initially):

NetworkObject.SpawnWithObservers = false;
NetworkObject.Spawn();

See Spawning With (or Without) Observers for more information.