- Home /
Dictionary in inspector
We all know Dictionaries do not appear in the Editor. What would be a way to get them to appear?
Suppose I have:
[Serializable]
public class MySerializableObject
{
public float Name;
public float Description;
}
public Dictionary<string, MySerializableObject> MyDictionary;
Strings and Serializable objects both appear in the editor. How would I get MyDictionary (and all Dictionaries really) to display with their default inspectors for Key types and Value types?
Would a PropertyDrawer be the solution?
Any help / examples / solutions would be appreciated.
Answer by Helical · Oct 22, 2014 at 11:49 AM
You could just do a hack, like you do for anything serious in unity.
expose a normal array.
[Serializable]
public struct NamedImage {
public string name;
public Texture2D image;
}
public NamedImage[] pictures;
then at the Start() or Awake(), or whenever your mind is flipped for it. put the array manually in a Hash or Dictionary or whatever. It looks alright in the inspector.
If it looks like a Hashtable, walks like a Hashtable, acts like a Hashtable, guess what, its a Hashtable.
While this is a nice workaround it DOES not act like a Hashtable. This implementaton allows any number of images to share the same name. You should at least test if the resukting Dictonary has the same number of members as the source array.
Agree :), but then again Unity is all about cutting corners.
"If it looks like a Hashtable, walks like a Hashtable, acts like a Hashtable, guess what, its a Hashtable."
yes but it doesn't act like one and completely defeats the point of having one, this is a junk answer
The idea is that you populate a hash table in Start/Awake, and then you have the functionality available. Serializing a dictionary is, after all, turning it into a "list". Hence that O(n) operation at startup is more or less unavoidable (it could possibly be slightly more efficient if native, but probably not a lot).
That said, I do think this is something unity should have added native support for a long time ago. It's pretty fundamental.
Indeed. And I'd also point out that unless your objective is to end up with a mess, Unity is not all about cutting corners. That's a recipe for pain, regardless of whether you're in low level c++ or nice friendly unity. Not good advice.
AGREED!! lol, i will be using Hashsets for..well what they're for!
it would be nice to display Hashsets and Dictionaries in the editor but i fear dumping them out to debug lists for my inspection is the better way, for the sake of my time anyway. I personally might make some compiler directives to filter out this debug stuff for the final build
It's always funny to watch the Unity community come up with new hacks. And the developers of the engine cannot make elementary functionality.
Ordinary Unity team dev:
"Make SerializeField for Dictionary? Why?"
"Making the community suffer? This is what we need!"
You just registered to leave that comment? If it's elementary, then surely you can implement that feature yourself?
Answer by frarees · Oct 27, 2014 at 02:47 PM
Use ISerializationCallbackReceiver to let Unity serialize the keys and values of your dictionary. From there, you can access both lists and create your custom editor.
You have an example on how to properly serialize a dictionary in the link I provided before. That will render the dictionary as two different lists, so it will be actually visible. For a editor/layout implementation, I let you investigate on your own :) (if you're starting editor scripting, this tutorial is a really good one)
Answer by MakeCodeNow · Feb 17, 2014 at 11:15 PM
It's a PITA but you'd have to do the rendering yourself. Also note that Unity will not serialize/save/load dictionary for you. For this reason, a lot of people store things in Lists and then build a Dictionary at Start to make lookups faster.
I'd suggest building the dictionary using the ISerializationCallbackReceiver interface, not on Start.
Answer by jamesbean · Jan 13 at 08:40 PM
I was just facing this problem. I tried some custom serialization, to find that it gives me trouble when switching to the HTML5 platform. I am not really savvy on serialization and its shenanigans, so I needed to implement a different solution.
In the end, my solution is a variation on the hack @Helical described:
Using platform-dependent compilation, I declare a serialized key-value struct for the dictionary I want to fill, and an array of this struct. This struct, array, and the function to use them, will only exist for the editor.
Create a scriptable object to contain the dictionary. This object I will be using in the game.
Run an editor function that stores the data from the array into the dictionary in the scriptableObject. Since it is an asset, you will need to use the AssetDatabase class to 1) set it dirty before modifying it; 2) save the AssetDatabase, 3) reload the assetDatabase.
The result is a visible list of items available in the editor, a plain old dictionary that will leave no extra trash and require no extra processing in the application, and an editor function that saves the first into the second.
Of couse, as some have mentioned, nothing stops you from putting duplicated key values into the array, so you need to be careful, or have the "Dumping" function check for errors like this. Other than that, I think it is a good compromise. This process of using editor-only variables and functions to process and store data into scriptableObjects has been pretty reliable to me, and I have been using it quite frequently with no problems.