この投稿は「K3 Advent Calendar 2023」の10日目の記事です
Unityの標準機能では、Dictionary
型の変数はシリアライズされません。これは、多くのUnity開発者にとって課題となっています。
本記事では、SerializedDictionary
を使ってこの問題を解決する方法を紹介します。
コード
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SerializedDictionary<K, V> : Dictionary<K, V>, ISerializationCallbackReceiver
{
[System.Serializable]
internal class KeyValue
{
public K Key;
public V Value;
public KeyValue(K key, V value)
{
Key = key;
Value = value;
}
}
[SerializeField] List<KeyValue> m_list;
public virtual K DefaultKey => default;
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
Clear();
foreach (var item in m_list)
{
this[ContainsKey(item.Key) ? DefaultKey : item.Key] = item.Value;
}
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
m_list = new List<KeyValue>(Count);
foreach (var kvp in this)
{
m_list.Add(new KeyValue(kvp.Key, kvp.Value));
}
}
}
[System.Serializable]
public class SerializedDictionary<V> : SerializedDictionary<string, V>
{
public override string DefaultKey => string.Empty;
}
[System.Serializable]
public class SerializedDictionaryC<K, V> : SerializedDictionary<K, V> where K : new()
{
public override K DefaultKey => new();
}
使用例
追加でCustomクラスは作る必要はなく、そのまま利用可能です。
[SerializeField] SerializedDictionary<int, string> m_PrimitiveDic;
[SerializeField] SerializedDictionary<string> m_StringDic;
[SerializeField] SerializedDictionaryC<Vector3, string> m_ClassDid;
Unity Editorでの表示
本クラスの利点
Dictionaryをベースで継承しているため、Dictionaryに存在しているメソッドがそのまま使えます
また、インスペクターで用意にデータの編集も可能となっています。
他との比較
プロダクト | Dictionary | Inspector | 補足 |
---|---|---|---|
本プロダクト | 継承 | 容易 | コード数少ない |
Core RP(Unity) | IDictionary | 不可 | 公式 |
neuecc/SerializableDictionary | IDictionary | 不可 | 高パフォーマンス / クラス別途定義 |
baba-s/UniSerializableDictionary | 内部List | 可能 | クラス別途定義 |
UnityのSerializableFieldで連想配列(Dictinary)を扱いたい | 配列 | 可能 | Dictionary的扱い不可 |