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

Question NetworkList exploding with custom struct that works with NetworkVariable

Discussion in 'Netcode for GameObjects' started by hoesterey, Jan 17, 2022.

  1. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    I'm absolutely stuck here. I have a class that doesn't serialize and transfer across the network in a Network Variable, though I get no errors. But when used in a NetworkList it produces the following error:
    UnityException: EditorPrefsGetInt is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'StatusBehavior' on game object 'PlayerNetworkedGame'.

    //No Error
    private NetworkVariable<StatusEffect> m_Status1 = new NetworkVariable<StatusEffect>();
    //Above Error.
    private NetworkList<StatusEffect> m_Status = new NetworkList<StatusEffect>();


    See the struct below.
    Code (CSharp):
    1. [Serializable]
    2.     public partial struct StatusEffect: INetworkSerializable, IEquatable<StatusEffect>
    3.     {
    4.  
    5.         public int m_Hash; //hash be faster then string
    6.         public double m_EndTime;//server time or round time depending on combat type.
    7.         public int m_Level;
    8.         public ulong m_Owner;  //client ID
    9.         public string m_DisplayName => data.DisplayName;
    10.         public string m_Discription => data.Description;
    11.         public string name => data.name;
    12.         public Sprite m_Sprite => data.Sprite;
    13.         public StatusEffectData.Statuses m_Status => data.Status;
    14.         public GameplayDefs.Dice[] m_EffectDice => data.EffectDice;
    15.         public int m_EffectValue => data.EffectValue;
    16.         public StatusEffectData.SaveTypes m_SaveType => data.SaveType;
    17.         public StatusEffectData.SaveFrequencys m_SaveFrequency => data.SaveFrequency;
    18.         public StatusEffectData.ApplyFrequencys m_ApplyFrequency => data.ApplyFrequency;
    19.         public int m_SaveValue => data.SaveValue;
    20.  
    21.         public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    22.         {
    23.             serializer.SerializeValue(ref m_Hash);
    24.             serializer.SerializeValue(ref m_EndTime);
    25.             serializer.SerializeValue(ref m_Level);
    26.             serializer.SerializeValue(ref m_Owner);
    27.         }
    28.  
    29.         public bool Equals(StatusEffect other)
    30.         {
    31.             return m_Hash .Equals(other.m_Hash) && m_EndTime.Equals(other.m_EndTime) && m_Level.Equals(other.m_Level) && m_Owner.Equals(other.m_Owner);
    32.         }
    33.  
    34.         public StatusEffect(StatusEffectData data, ulong ownerClientID,  int level, int durationModifier)
    35.         {
    36.             m_Owner = ownerClientID;
    37.             m_Hash = data.name.GetStableHashCode();
    38.             m_Level = level;
    39.             double gameTime = ZoneInstance.Instance.GetGameTime();
    40.             m_EndTime = data.Duration + gameTime;//TODO add round or network time
    41.         }
    42.  
    43.         public StatusEffectData data
    44.         {
    45.             get
    46.             {
    47.                 // show a useful error message if the key can't be found
    48.                 // note: ScriptableSkill.OnValidate 'is in resource folder' check
    49.                 //       causes Unity SendMessage warnings and false positives.
    50.                 //       this solution is a lot better.
    51.                 if (!StatusEffectLookup.All.ContainsKey(m_Hash))
    52.                     throw new KeyNotFoundException("There is no ScriptableSkill with hash=" + m_Hash + ". Make sure that all ScriptableSkills are in the Resources folder so they are loaded properly.");
    53.                 return (StatusEffectData)StatusEffectLookup.All[m_Hash];
    54.             }
    55.         }
    56. }
     
    Last edited: Jan 17, 2022
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    676
    daxiongmao likes this.
  3. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659

    Turns out I can't get anything custom to serialize with NetworkVariables either. Simplest test ever (even tried not declaring till awake). Simplest test I can think to make does not work :(

    Displays as 10 on the host/server and 0 on the client.

    //Class to seralize
    Code (CSharp):
    1.  
    2. using Unity.Netcode;
    3.  
    4.  
    5. public struct TestNet : INetworkSerializable
    6. {
    7.     public int m_Hash;
    8.     public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    9.     {
    10.         serializer.SerializeValue(ref m_Hash);
    11.     }
    12. }
    13.  
    //Class that should display numbers on the client.
    private NetworkVariable<TestNet> m_Status1;
    Code (CSharp):
    1. private void Awake()
    2.         {
    3.              m_Status1 = new NetworkVariable<TestNet>();
    4.         }
    5.  
    6. bool b = false;
    7. private void Update()
    8.         {
    9.    
    10.             if(!b && IsServer)
    11.             {
    12.                 TestNet t = new TestNet();
    13.                 t.m_Hash = 10;
    14.                 m_Status1.Value = t
    15.                 Debug.LogError("Server created test");
    16.                 b = true;
    17.            
    18.             }
    19.             if(IsClient)
    20.             {
    21.                 Debug.LogError(m_Status1.Value.m_Hash);
    22.             }
    23.             else
    24.             {
    25.                 Debug.LogError("?");
    26.             }
    27.         }
    28.  
     
  4. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    I got the simple example above to work by moving the component off the player objects...but that makes no sense :(
     
  5. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    Ok,
    So. You were correct. moving the =new to "Awake" (wow that is dirty) I got the test and my original example working! It seamed that ANYWHERE in the project I defined a net list defined inline seamed to silently nuke the whole project so I had to fix that everywhere before it worked.

    Also random question. Anyone know where I can get NetworkDictionary? I'm not seeing it in the library anymore. If I have working NetworkVars/Lists/Dictionaries/ and RPCS its all I need to develop. This all should be stable in the 3-5 years we have to finish the game?
     
  6. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    676
    NetworkDictionary was removed and there's no future plans to support them as far as I know.
     
  7. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    659
    That is sad. I can work around lack of dictionaries but they are great for stat and resource management.

    Cant work around Lack of lists though so happy those are working.