- Home /
Custom Editor for Map/Dictionary in Unity
I'm trying to build my own little ResourceManager in Unity that will allow me to tag resources (ranging from materials to prefabs) to a label in the editor, and then access them in game.
The ResourceManager itself is really easy to write- it's just a Dictionary. However the Unity Editor doesn't seem to be able to serialize (and thus render) Dictionaries.
To get around this, I created a list of key-value pairs which gets loaded into the dictionary by unity. That way Unity gets its list and I get my Dictionary. However, when I try and run the code shown below, I can only add a single entry to the list. Any idea what I'm doing wrong?
ResourceManager.cs
using UnityEngine;
using System.Collections.Generic;
public class ResourceManager : MonoBehaviour, ISerializationCallbackReceiver {
private Dictionary<string, Object> resources = new Dictionary<string, Object>();
#region Unity
// Unity doesn't know how to deal with maps, so we give it a list to work with
public List<ResourceEntry> entries;
// Dictionary -> List
public void OnBeforeSerialize() {
entries.Clear();
foreach(string key in resources.Keys) {
entries.Add(new ResourceEntry(key, resources[key]));
}
}
// List -> Dictionary
public void OnAfterDeserialize() {
resources = new Dictionary<string, Object>();
foreach(ResourceEntry entry in entries) {
resources[entry.key] = entry.value;
}
}
[System.Serializable]
public class ResourceEntry {
public string key;
public Object value;
public ResourceEntry() {}
public ResourceEntry(string key, Object value) {
this.key = key;
this.value = value;
}
}
#endregion
private static ResourceManager instance;
public static Object Get(string category, string key) {
instance = instance ?? GameObject.FindObjectOfType<ResourceManager>();
if( instance.resources.ContainsKey(key)) {
return instance.resources[key];
} else {
return null;
}
}
}
ResourceManagerEditor.cs
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(ResourceManager))]
public class ResourceManagerEditor : Editor {
private ReorderableList list;
public void OnEnable() {
list = new ReorderableList(serializedObject, serializedObject.FindProperty("entries"), true, true, true, true);
list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => {
SerializedProperty element = list.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, 60, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("key"), GUIContent.none);
EditorGUI.PropertyField(new Rect(rect.x + 70, rect.y, 160, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("value"), GUIContent.none);
};
list.drawHeaderCallback = (Rect rect) => {
EditorGUI.LabelField(rect, "Resources");
};
}
public override void OnInspectorGUI() {
serializedObject.Update();
list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
Your answer
Follow this Question
Related Questions
Dictionary in inspector 4 Answers
CustomEditor for 2 List to look like dictionary 1 Answer
Scriptable Object resets after Unity is closed 2 Answers
Dictionairy Serialization Problem: Keys and values get lost 0 Answers
Is EditorUtility.SetDirty restricted to prefabs or inspected GameObject? 5 Answers