I created a custom component that uses a custom editor.
In this editor I set a number of fields. When saving the prefab, only some of those fields are saved. Specifically, normal fields like int, string, float save just fine. But I have some fields that store data for the following structure:
[System.Serializable]
public class MovementVariableModifierData
{
[ItemType]
public string modifierItemID = "";
public int modifierItemIdx;
[SerializeField]
public Dictionary<string, float> multipliers = new Dictionary<string, float>();
[SerializeField]
public Dictionary<string, float> addends = new Dictionary<string, float>();
}
Furthermore, the class for which the editor is being used is actually storing data in an array of that structure, so into a MovementVariableModifierData[] Modifiers
array. e.g.:
public class MyClass
{
Modifiers = new MovementVariableModifierData[0];
}
In the custom inspector, the fields are modified like so inside the OnInspectorGUI
method:
// Custom Editor Code:
// read old values and copy them to new list
tmpModifiers = new List<MovementVariableModifierData>(Modifiers)
for (int i = 0; i < tmpModifiers.Count; i++)
{
// MODIFY Int and String - these get saved
tmpModifiers[i].modifierItemIdx = EditorGUILayout.Popup(new GUIContent("Item ID:"), tmpModifiers[i].modifierItemIdx, itemTypes);
tmpModifiers[i].modifierItemID = itemTypes[tmpModifiers[i].modifierItemIdx];
// MODIFY Dictionary - Doesn't get saved
// Set default value
if (!tmpModifiers[i].multipliers.ContainsKey("Key1")) tmpModifiers[i].multipliers["Key1"] = 1.0f;
tmpModifiers[i].multipliers["Key1"] = EditorGUILayout.FloatField(new GUIContent("Key 1:"), tmpModifiers[i].multipliers["Key1"]);
// There's many more of these in the loop but they all use this exact pattern.
}
Modifiers = tmpModifiers.ToArray();
So basically the Custom Editor's target class has a MovementVariableModifierData[]
array, and it contains some Dictionary<string, float>
fields that I'm trying to update and save via the custom editor.
The data seems to update just fine when I Debug.Log() it, and it shows up correctly in the inspector, but when i save the prefab and then close and reopen it, the values stored in the dictionaries reset. The value stored in the int/string field of modifierItemID
and modifierItenIdx
, and adding new MovementVariableModifierData
entries to the Modifiers
array also saves successfully (but again, not their dictionary values).
One thing I noticed is that while the returned values are correct, on the next call to OnInspectorGUI()
the dictionaries have reset.
I am wracking my brain and can't for the life of me figure out why only the dictionaries reset but not the int and string. I have marked them and the class they're part of as [Serializable]. I have also tried using List<KeyValuePair<string, float>>
instead of dictionaries to store the data and still have the issue.
As derHugo mentioned Dictionary and KeyValuePair are not Serializable. Create custom modifiers and addends using a record that are Serializable.
[Serializable]
public class MovementVariableModifierData
{
private string _modifierItemID = "";
public string ModifierItemID => _modifierItemID;
private int _modifierItemIdx;
public int ModifierItemIdx => _modifierItemIdx;
private Multiplier[] _multipliers;
public Multiplier[] Multipliers => _multipliers;
private Addend[] _addends;
public Addend[] Addends => _addends;
public MovementVariableModifierData(string modifierItemID,
int modifierItemIdx, Multiplier[] multipliers, Addend[] addends)
{
_modifierItemID = modifierItemID;
_modifierItemIdx = modifierItemIdx;
_multipliers = multipliers;
_addends = addends;
}
}
[Serializable]
public record class Addend(string Key, float Value) { }
[Serializable]
public record class Multiplier(string Key, float Value) { }