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 NetworkObject
s visible to a single client (static method):
/// networkObjects is of type List<NetworkObject>
NetworkObject.NetworkShow(networkObjects, clientId);
Make several NetworkObject
s 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.