How to use OnBeforeSerialize() and OnAfterDeserialize() to convert Dictionaries

So how do I use OnBeforeSerialize() and OnAfterDeserialize() on a dictionary? I know that I have to convert it to an array of keys and an array of what I want to be serialized, but how would I use this? Wouldn’t it just say that you can’t convert a dictionary to two arrays when I’ll try to use it? Please explain to me how this works. Thank you! I’m sorry if I sound impatient.

OnBeforeSerialize and OnAfterDeserialize should simply do the opposite from each other. So in OnBeforeSerialize you would copy the data from the actual dictionary into the structure that can actually be serialized so when Unity does serialized the object afterwards, the actual data is preserved in that extra structure. In OnAfterDeserialize you would do the opposite. That means you copy the data back from your structure that was serialized by Untiy back into the dictionary. That’s all. You would still use your dictionary just as it is.

ps: I would not recommend using two seperate arrays or Lists for the keys and the values. It would make more sense when you use your own key-value pair struct or class and create one List or array of that type. Of course that class / struct needs to be serializable. Using one array / List makes it easier to reconstruct the dictionary from that list as you just have to go through the list and you always have the key and value paired properly. With seierate arrays things can easily go wrong when you for example delete one key in the inspector.

Specifically you can do something like this:

[System.Serializable]
public class DictionaryWrapper<TKey, TValue> : ISerializationCallbackReceiver
{
    [System.Serializable]
    public class KeyValue
    {
        public TKey key;
        public TValue value;
    }

    private Dictionary<TKey, TValue> m_Dict = new Dictionary<TKey, TValue>();
    public Dictionary<TKey, TValue> Dict => m_Dict;

    [SerializeField]
    private List<KeyValue> m_Data = new List<KeyValue>();

    public void OnAfterDeserialize()
    {
        m_Dict.Clear();
        foreach(var kv  in m_Data)
            m_Dict.Add(kv.key, kv.value);
    }

    public void OnBeforeSerialize()
    {
        m_Data.Clear();
        foreach (var kv in m_Dict)
            m_Data.Add(new KeyValue { key = kv.Key, value = kv.Value });
    }
}

You can use this class instead of a Dictionary in a MonoBehaviour or ScriptableObject. Just access the “Dict” property of the class and use it like a dictionary. Of course you can simply edit the serialized entries in the inspector which is there just a List of “KeyValue” instances.

Regardless of this, there’s rarely really a usecase for serializing a dictionary. A lot don’t seem to really understand when to use a dictionary. A Dictionary is a data structure for a fast look ups at runtime.

Bro, I was messing around with @Bunny83 's code and discovered how to look at the code for system classes, and copying some of that, I was able to add a little to his code. Hope it helps!

[System.Serializable]
public class DictionaryWrapper<TKey, TValue> : ISerializationCallbackReceiver
{
    [System.Serializable]
    public class KeyValue
    {
        public TKey key;
        public TValue value;
    }

    private Dictionary<TKey, TValue> m_Dict = new Dictionary<TKey, TValue>();
    public Dictionary<TKey, TValue> Dict => m_Dict;

    public bool ContainsKey(TKey kay)
    {
        return m_Dict.ContainsKey(kay);
    }

    public void Add(TKey kay, TValue val)
    {
        m_Dict.Add(kay, val);
    }

    public TValue this[TKey index] { get => m_Dict[index]; }

    [SerializeField]
    private List<KeyValue> m_Data = new List<KeyValue>();

    public void OnAfterDeserialize()
    {
        m_Dict.Clear();
        foreach (var kv in m_Data)
            m_Dict.Add(kv.key, kv.value);
    }

    public void OnBeforeSerialize()
    {
        m_Data.Clear();
        foreach (var kv in m_Dict)
            m_Data.Add(new KeyValue { key = kv.Key, value = kv.Value });
    }
}