Search Unity

Non-nullable values in NetworkVariable<>

Discussion in 'Netcode for GameObjects' started by ppudlik, Dec 14, 2021.

  1. ppudlik

    ppudlik

    Joined:
    Dec 11, 2020
    Posts:
    3
    Hey guys, I'm having difficulties using my own struct in NetworkVariable<>. I've done everything as shown in INetworkSerializable documentation.

    Code (CSharp):
    1. public struct PData : INetworkSerializable
    2. {
    3.     int PlayerID;
    4.     string PlayerName;
    5.  
    6.     public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    7.     {
    8.         serializer.SerializeValue(ref PlayerID);
    9.         serializer.SerializeValue(ref PlayerName);
    10.     }
    11. }
    12.  
    13. public class PlayerData : NetworkBehaviour
    14. {
    15.  
    16.     public NetworkVariable<PData> Data = new NetworkVariable<PData>();
    Any ideas why VisualStudio returns:

    "Error CS8377 The type 'PData' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'NetworkVariable<T>' Assembly-CSharp C:\UnityProj\hexmap\Assets\Scripts\PlayerData.cs 23 Active"

    I noticed it works fine, if I remove any string variables from the struct and I delete serializer stuff. It's as if the serializer wasn't serializing anything?
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    It says everything in the struct must be non-nullable value type. A string is nullable.
     
  3. ppudlik

    ppudlik

    Joined:
    Dec 11, 2020
    Posts:
    3
    Thank you for your reply. I see! I thought the serializing itself was going to make them non-nullable.

    I just learned through youtube that Unity.Collections contains fixed size Strings, which can be used for this purpose:)
     
    Last edited: Dec 15, 2021
    UnityGio likes this.
  4. Blamkay

    Blamkay

    Joined:
    Apr 3, 2020
    Posts:
    1
    Wait so I want to use a string as a name and im getting a similar error, how exactly do i make a string "Non-nullable"?
     
  5. itisMarcii_

    itisMarcii_

    Joined:
    Apr 5, 2022
    Posts:
    111
    Use "INetworkSerializeByMemcpy" instead of "INetworkSerializable", they canged it in 1.0.0-pre.8
     
  6. alexogorek

    alexogorek

    Joined:
    Jun 21, 2018
    Posts:
    18
    Going off what itisMarcii_ said, you can create a "string wrapper" class

    I copied this from the Boss Room project:

    Code (CSharp):
    1. /// <summary>
    2. /// Wrapping FixedString so that if we want to change player name max size in the future, we only do it once here
    3. /// </summary>
    4. public struct FixedPlayerName : INetworkSerializable {
    5.     ForceNetworkSerializeByMemcpy<FixedString32Bytes> m_Name; // using ForceNetworkSerializeByMemcpy to force compatibility between FixedString and NetworkSerializable
    6.     public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter {
    7.         serializer.SerializeValue(ref m_Name);
    8.     }
    9.  
    10.     public override string ToString() {
    11.         return m_Name.Value.ToString();
    12.     }
    13.  
    14.     public static implicit operator string(FixedPlayerName s) => s.ToString();
    15.     public static implicit operator FixedPlayerName(string s) => new FixedPlayerName() { m_Name = new FixedString32Bytes(s) };
    16. }
    Then you can use it like this:
    Code (CSharp):
    1.  
    2. [System.Serializable]
    3. public struct Player : INetworkSerializable, IEquatable<Player> {
    4.     public FixedPlayerName name;
    5.     public ulong clientId;
    6.     ...
    7. }
    it will essentially act as a normal string because of the overloaded operators
     
    gabagpereira likes this.
  7. alexogorek

    alexogorek

    Joined:
    Jun 21, 2018
    Posts:
    18
    Similarly i'm looking at adding a version for
    List<int>
    or
    Dictionary<int, int>
    since i want to send product IDs / count mapping and sync them between server-client. Not sure if this is the right approach but definitely feels easiest to track.