NetworkList exploding with custom struct that works with NetworkVariable

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 m_Status1 = new NetworkVariable();
//Above Error.
private NetworkList m_Status = new NetworkList();

See the struct below.

[Serializable]
    public partial struct StatusEffect: INetworkSerializable, IEquatable<StatusEffect>
    {

        public int m_Hash; //hash be faster then string
        public double m_EndTime;//server time or round time depending on combat type.
        public int m_Level;
        public ulong m_Owner;  //client ID
        public string m_DisplayName => data.DisplayName;
        public string m_Discription => data.Description;
        public string name => data.name;
        public Sprite m_Sprite => data.Sprite;
        public StatusEffectData.Statuses m_Status => data.Status;
        public GameplayDefs.Dice[] m_EffectDice => data.EffectDice;
        public int m_EffectValue => data.EffectValue;
        public StatusEffectData.SaveTypes m_SaveType => data.SaveType;
        public StatusEffectData.SaveFrequencys m_SaveFrequency => data.SaveFrequency;
        public StatusEffectData.ApplyFrequencys m_ApplyFrequency => data.ApplyFrequency;
        public int m_SaveValue => data.SaveValue;

        public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
        {
            serializer.SerializeValue(ref m_Hash);
            serializer.SerializeValue(ref m_EndTime);
            serializer.SerializeValue(ref m_Level);
            serializer.SerializeValue(ref m_Owner);
        }

        public bool Equals(StatusEffect other)
        {
            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);
        }

        public StatusEffect(StatusEffectData data, ulong ownerClientID,  int level, int durationModifier)
        {
            m_Owner = ownerClientID;
            m_Hash = data.name.GetStableHashCode();
            m_Level = level;
            double gameTime = ZoneInstance.Instance.GetGameTime();
            m_EndTime = data.Duration + gameTime;//TODO add round or network time
        }

        public StatusEffectData data
        {
            get
            {
                // show a useful error message if the key can't be found
                // note: ScriptableSkill.OnValidate 'is in resource folder' check
                //       causes Unity SendMessage warnings and false positives.
                //       this solution is a lot better.
                if (!StatusEffectLookup.All.ContainsKey(m_Hash))
                    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.");
                return (StatusEffectData)StatusEffectLookup.All[m_Hash];
            }
        }
}

The error is actually on NetworkList and not your class. Seems NetworkLists don’t like to be instantiated when declared, so I would put the new NetworkList(); in somewhere like Awake.

I’ve not checked if it’s fixed in pre.4 but maybe not as there’s an open issue for it here NetworkList - UnityException: EditorPrefsGetInt is not allowed to be called · Issue #1367 · Unity-Technologies/com.unity.netcode.gameobjects · GitHub

1 Like

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 :frowning:

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

//Class to seralize

using Unity.Netcode;


public struct TestNet : INetworkSerializable
{
    public int m_Hash;
    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref m_Hash);
    }
}

//Class that should display numbers on the client.
private NetworkVariable m_Status1;

private void Awake()
        {
             m_Status1 = new NetworkVariable<TestNet>();
        }

bool b = false;
private void Update()
        {
    
            if(!b && IsServer)
            {
                TestNet t = new TestNet();
                t.m_Hash = 10;
                m_Status1.Value = t
                Debug.LogError("Server created test");
                b = true;
            
            }
            if(IsClient)
            {
                Debug.LogError(m_Status1.Value.m_Hash);
            }
            else
            {
                Debug.LogError("?");
            }
        }

I got the simple example above to work by moving the component off the player objects…but that makes no sense :frowning:

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?

NetworkDictionary was removed and there’s no future plans to support them as far as I know.

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.