Serializing Dictionaries

Serializing Dictionaries With Odin

The Odin Serializer makes it easy to serialize dictionaries. Just inherit from one of our Serialized- classes, and you are good to go!

public MyScriptableObject : SerializedScriptableObject
{
	// This Dictionary will be serialized by Odin.
	public Dictionary<int, string> IntStringMap;
}

That's it! You can read more about using the Odin Serializer here: Implementing The Odin Serializer.

Serializing Dictionaries With Unity

Unity does not support Dictionary serialization out of the box, but by exploiting Unity's serialization protocol (See On Unitys Serialization Procotol) it can be done.

By making a new class that inherits both Dictionary and Unity's ISerializationCallbackReceiver interface, we can convert the Dictionary data to a format that Unity can serialize.

public abstract class UnitySerializedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
	[SerializeField, HideInInspector]
	private List<TKey> keyData = new List<TKey>();
	
	[SerializeField, HideInInspector]
	private List<TValue> valueData = new List<TValue>();

    void ISerializationCallbackReceiver.OnAfterDeserialize()
    {
		this.Clear();
		for (int i = 0; i < this.keyData.Count && i < this.valueData.Count; i++)
		{
			this[this.keyData[i]] = this.valueData[i];
		}
    }

    void ISerializationCallbackReceiver.OnBeforeSerialize()
    {
		this.keyData.Clear();
		this.valueData.Clear();

		foreach (var item in this)
		{
			this.keyData.Add(item.Key);
			this.valueData.Add(item.Value);
		}
    }
}

Because Unity does not serialize generic types, it is necessary to make a concrete Dictionary type by inheriting from the UnitySerializedDictionary:

[Serializable]
public class KeyCodeGameObjectListDictionary : UnitySerializedDictionary<KeyCode, List<GameObject>> { }

[Serializable]
public class StringScriptableObjectDictionary : UnitySerializedDictionary<string, ScriptableObject> { }

And, with that, we have Dictionaries that can be used in Unity.

public class MyScriptableObject : ScriptableObject
{
	public KeyCodeGameObjectListDictionary KeyCodeMap;

	public StringScriptableObjectDictionary StringMap;
}

Of course, these UnitySerializedDictionaries can be like any normal Dictionary, and even show up in Odin Inspector as ordinary Dictionaries. Do note that there may be some strange interactions with Unity's prefab modification system, and prefab-modified values may not properly show up as such in the inspector.