Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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,716
    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:
    107
    Use "INetworkSerializeByMemcpy" instead of "INetworkSerializable", they canged it in 1.0.0-pre.8
     
  6. alexogorek

    alexogorek

    Joined:
    Jun 21, 2018
    Posts:
    14
    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:
    14
    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.