[Unity] How to serialize a Dictionary

Cet article sur Unity est disponible en français

 

Unity doesn’t support Dictionary serialization.

The right way for doing it is simply given by the Unity’s documentation, but if you don’t have the right pointer or keyword when you start googling for it, you’ll face one of the main Unity’s downside : the incredible amount of bad / of subject / out of date solutions…

As a resume of the documentation, the key is this interface ISerializationCallbackReceiver. It lets you execute your custom serialize/deserialize code and this way you can use List to store the Keys and Values of your Dictionary.

Here is the code snippet :

 

using UnityEngine;
using System;
using System.Collections.Generic;

public class SerializationCallbackScript : MonoBehaviour, ISerializationCallbackReceiver
{
	public List<int> _keys = new List<int>();
	public List<string> _values = new List<string>();

	//Unity doesn't know how to serialize a Dictionary
	public Dictionary<int,string> _myDictionary = new Dictionary<int,string>()
	{
		{3, "I"},
		{4, "Love"},
		{5, "Unity"},
	};
	
	public void OnBeforeSerialize()
	{
		_keys.Clear();
		_values.Clear();

		foreach( var kvp in _myDictionary )
		{
			_keys.Add( kvp.Key );
			_values.Add( kvp.Value );
		}
	}

	public void OnAfterDeserialize()
	{
		_myDictionary = new Dictionary<int, string>();

		for(var i = 0; i != Math.Min( _keys.Count, _values.Count ); i++ )
			_myDictionary.Add( _keys[i], _values[i] );
	}

	void OnGUI()
	{
		foreach( var kvp in _myDictionary )
				GUILayout.Label( "Key: " + kvp.Key + " value: " + kvp.Value );
	}
}

Be aware that List doesn’t support null values serialization, so you need to handle it by yourself.

The solution is not perfect of course, as you’ll have to be sure your null string will never be a valid value.

Here is the modified version I use :

public void OnBeforeSerialize()
        {
            _keys.Clear();
            _values.Clear();

            foreach (var kvp in _myDictionary)
            {
                _keys.Add(kvp.Key);
                if (kvp.Value != null)
                    _values.Add(kvp.Value);
                else
                    _values.Add(NULL_STRING);
            }
        }

        public void OnAfterDeserialize()
        {
            _myDictionary = new Dictionary<SystemLanguage, string>();

            for (var i = 0; i != Math.Min(_keys.Count, _values.Count); i++)
            {
                if (_values[i].Equals(NULL_STRING))
                {
                    _myDictionary.Add(_keys[i], null);
                }
                else
                {
                    _myDictionary.Add(_keys[i], _values[i]);
                }
            }
        }

 

Hope this saves you some time, happy coding 😉

Leave a Reply

Your email address will not be published. Required fields are marked *