Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Bug Network Serialization error

Discussion in 'Netcode for GameObjects' started by ArneXarpy, Mar 29, 2024.

  1. ArneXarpy

    ArneXarpy

    Joined:
    Feb 15, 2024
    Posts:
    2
    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.

    Code (CSharp):
    1. public class DisableHost: NetworkBehaviour
    2.     {
    3.         public override void OnNetworkSpawn()
    4.         {
    5.             base.OnNetworkSpawn();
    6.            
    7.             ulong hostId = NetworkManager.Singleton.LocalClientId;
    8.             // Note that owner always spawns network objects
    9.             ulong networkObjOwner = NetworkObject.OwnerClientId;
    10.  
    11.             if (hostId == networkObjOwner)
    12.             {
    13.                 // Default is true
    14.                 gameObject.SetActive(false);
    15.             }
    16.         }
    17.     }

    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:

    Code (CSharp):
    1. public class DisableHost: NetworkBehaviour
    2.     {
    3.         public override void OnNetworkSpawn()
    4.         {
    5.             base.OnNetworkSpawn();
    6.            
    7.             // Nothing to see here
    8.         }
    9.     }
    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!

    upload_2024-3-29_14-7-19.png
    upload_2024-3-29_14-7-46.png
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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.