Dictionary empty upon play

I am creating an editor window, and when you click on an object in the Hierarchy, it displays a button if the object doesn’t have a particular Component on it. When you click the button it adds the Component.

The Component has a Dictionary in it. My editor script allows you to add items to the dictionary for that Game Object. It works fine within edit mode, it saves the data that was added to it, but once you press play all the data in the dictionary gets removed and it becomes empty. When I stop the game the Dictionary does not repopulate with what was there, it just stays empty. What is causing this to happen?

Here is the Component, it contains other Non-Monobehaviour methods that are only called within the EditorWindow class.

public class DeventSystem : MonoBehaviour {
    Dictionary<Devent, List<Deaction>> devents = new Dictionary<Devent, List<Deaction>>();
}

I now just found out I cannot serialize a dictionary, I guess I will have to take another approach.

For serializing a dictionary, the easiest way to get it up and running is to use ISerializationCallbackReceiver:

Create 2 private serialized arrays, one for the keys, and one for the values. OnBeforeSerialize, dump the dictionary keys and values into the respective arrays. And OnAfterDeserialize, clear the dictionary (just in case) and fill it up based on the arrays.

//edit
heh, just noticed that’s actually the example unity has in the documentation:

They just use a List instead of an Array.

1 Like

That doesn’t seem to be working for me… Maybe I am doing something wrong… I still lose the dictionary upon play…

public class DeventSystem : MonoBehaviour, ISerializationCallbackReceiver {

    public List<Devent> deventsList = new List<Devent>();
    public List<List<Deaction>> deactionsList = new List<List<Deaction>>();

    public Dictionary<Devent, List<Deaction>> devents = new Dictionary<Devent, List<Deaction>>();

    public int Length {get { return devents.Count; } }

    public void OnBeforeSerialize(){
        deventsList.Clear();
        deactionsList.Clear();
        foreach(var entry in devents){
            deventsList.Add(entry.Key);
            deactionsList.Add(entry.Value);
        }
    }

    public void OnAfterDeserialize(){
        devents = new Dictionary<Devent, List<Deaction>>();
        for(int i = 0; i != Mathf.Min(deventsList.Count, deactionsList.Count); i++){
            devents.Add(deventsList[i], deactionsList[i]);
        }
    }
}

oh yeah… I don’t think lists of lists (or arrays of arrays) are serializable either.

You might have to create a wrapper for the list:

public class DeventSystem : MonoBehaviour, ISerializationCallbackReceiver
{

    public Dictionary<Devent, List<Deaction>> devents = new Dictionary<Devent, List<Deaction>>();
 
    [SerializeField()]
    [HideInInspector()]
    private Devent[] _devents_keys;
    [SerializeField()]
    [HideInInspector()]
    private ListWrapper[] _devents_values;

    void ISerializationCallbackReceiver.OnBeforeSerialize()
    {
        _devents_keys = new Devent[devents.Count];
        _devents_values = new ListWrapper[devents.Count];
     
        int i = 0;
        var e = devents.GetEnumerator();
        while(e.MoveNext())
        {
            _devents_keys[i] = e.Current.Key;
            _devents_values[i] = new ListWrapper(e.Current.Value);
            i++;
        }
    }

    void ISerializationCallbackReceiver.OnAfterDeserialize()
    {
        devents.Clear();
        int cnt = Mathf.Min(_devents_keys.Length, _devents_values.Length);
        for(int i = 0; i < cnt; i++)
        {
            devents.Add(_devents_keys[i], _devents_values[i].list);
        }
    }
 
    [System.Serializable()]
    public struct ListWrapper
    {
        public List<Deaction> list;
     
        public ListWrapper(List<Deaction> lst)
        {
            this.list = lst;
        }
    }
 
}

I also wrote the code a little different, I for some reason can’t write sloppy code like is sometimes found in the unity documentation.

Hmm, oddly when I play I get this error:

Which relates to this line:

int cnt = Mathf.Min(_devents_keys.Length, _devents_values.Length);

I fixed the error by initiating the arrays to a length of 0, but still it doesn’t keep the items, they still get removed.

Alright, I have got it working I just removed the dictionary completely and utilized your Wrappers to have two lists of objects.

This worked beautifully