Home > Software design >  Can't I serialize the Dictionary used by Unity?
Can't I serialize the Dictionary used by Unity?

Time:12-23

I want to see the Dictionary used by Unity on the Inspector. But I don't know if it's possible or not, and I don't know how.

Please tell me how to see the Dictionary on the inspector. Or you can tell me about other data structures similar to Dictionary in Unity.

CodePudding user response:

As suggested by @Daniel, odds are you can get away with using a Serializable attribute on a class with your desired data structure, then store it in a List.

However, if you insist on creating a Seraliable dictionary, you could use SerializableDictionary<TKey, TValue> as follows:

[System.Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField]
    private List<TKey> keys = new();

    [SerializeField]
    private List<TValue> values = new();

    public void OnBeforeSerialize()
    {
        keys.Clear();
        values.Clear();

        foreach (var pair in this)
        {
            keys.Add(pair.Key);
            values.Add(pair.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        Clear();

        if (keys.Count != values.Count)
            throw new System.Exception(
                $"There are {keys.Count} keys and {values.Count} values after deserialization. Make sure that both key and value types are serializable.");

        for (var i = 0; i < keys.Count; i  )
            Add(keys[i], values[i]);
    }
}

Then implement a SerializableDictionary in your code as follows:

[SerializeField]
private SerializableDictionary<string, int> _exampleSerializableDictionary = new()
{
    {"A", 10},
    {"B", 20},
    {"C", 30}
};

A visual example of SerializableDictionary

CodePudding user response:

Short answer is no, you can't serialize them.

But you have some options, I'll provide you with one.

Suppose you want to create a Dictionary<string, int>. You can create a class/struct that holds this information:

using System;

[Serializable]
public class StringIntPair {
    public string key;
    public int value;
}

And then, in your code, you can create a List<StringIntPair>, that will be visible on your inspector. This way you can set the values you want in the inspector.

Lastly, you can create a Dictionary<string, int> and populate it in Awake / Start method as you wish:

using System;

[Serializable]
public class YourClass : MonoBehaviour {
    
    public List<StringIntPair> exposedDictionary; 
    Dictionary<string, int> hiddenDictionary;

    void Awake(){
        foreach(StringIntPair pair in exposedDictionary)
            hiddenDictionary[pair.key] = pair.value;
    }    
}

And then you can use hiddenDictionary in the code as you wish.

  • Related