Network Serialization error

Hi, We are making a multiplayer VR game with Netcode for GameObjects where the host is always a computer. This means that the host does not need a NetworkPlayerPrefab to be spawned for him.

I tried fixing this by adding a script to the NetworkPlayer that detects if its the host and disables the gameobject in case it is.

public class DisableHost: NetworkBehaviour
    {
        public override void OnNetworkSpawn()
        {
            base.OnNetworkSpawn();
           
            ulong hostId = NetworkManager.Singleton.LocalClientId;
            // Note that owner always spawns network objects
            ulong networkObjOwner = NetworkObject.OwnerClientId;

            if (hostId == networkObjOwner)
            {
                // Default is true
                gameObject.SetActive(false);
            }
        }
    }

However, in doing so I have created the following error for my clients (VR headsets)

[Netcode] NetworkHead threw an exception during synchronization serialization, this NetworkBehaviour is being skipped and will not be synchronized! (same for NetworkLeftHand and NetworkRightHand)

Strangely enough when I remove the script everything works as expected (Besides the host having a NetworkPlayer ofcourse…), I have a hacky solution to this problem already, but I am more Curious as to why this is happening in the first place.

When I change my script to the following:

public class DisableHost: NetworkBehaviour
    {
        public override void OnNetworkSpawn()
        {
            base.OnNetworkSpawn();
           
            // Nothing to see here
        }
    }

It actually gives the error again! And at this point I am lost as to what is actually happening here. It only works when the script is not attached to it!

9737521--1392769--upload_2024-3-29_14-7-19.png

My recommended approach, since the players need to behave very differently, is not to rely on a single Player prefab at all. The player prefab reference is really only a convenience feature saving you just a few lines of code, namely Instantiate and SpawnAsPlayer plus having a NetworkObject prefab reference ready to instantiate.

Meaning: manually spawn prefabs “as players” for the clients but don’t spawn one for the host. This is the cleanest solution.

In all other cases you will keep running into issues because you have one “oddball” player that behaves differently, respectively has some components disabled (or all of them if you deactivate the object - not recommended).

The thing is your host player’s components may still receive RPCs and Netvars. But the components on the game object and the game object active state itself must be the same for all clients. The component lookup is done by index, but if the components are disabled on the host, you are likely going to see “index out of bounds” errors trying to find a NetworkBehaviour by index. Unless … maybe if you are carefully avoiding sending RPCs to the host (hypothesis).

Alternative:
You could program your player prefab in such a way that the host simply does not run any code that it shouldn’t. Add if(!IsHost) everywhere. This is of course tedious and error prone.

Perhaps Network visibility may help, by making the host player invisible to all. But then the host might still interfere with the game simply due to its presence.