Custom Editor to create multiple fields based on enum-values

In my current project I have a damageType enum and I want different races (ScriptableObject) to have different resistances/vulnerabilities to each damageType. I don’t want to hardcode a variable for each damageType in case I add/remove types, so I thought I’d be clever and use a custom editor to create a slider for each type in the enum and store the respective value in an array. I anticipated a problem, in that the array-Length does not get updated it the enum changes, but I don’t know a solution to this.

Does anyone here have a suggestion how to do it (better)?

(Dictionary does not work, since it doesn’t get serialized)

You can serialize a dictionary into two lists by implementing ISerializationCallbackReceiver.

But if you don’t want to do that, what about this:

public enum DamageType { Fire, Lightning, Ice }
public class Race : ScriptableObject {
    [Serializable]
    public DamageRating {
        public string damageTypeName;
        public float value;
    }
    public DamageRating[] damageRatings;
}
[CustomEditor(typeof(Race), true)]
public RaceEditor : Editor {
    public override void OnInspectorGUI() {
        serializedObject.Update();
        string[] enumNames = Enum.GetNames(typeof(DamageType));
        foreach (var enumName in enumNames) {
            DrawDamageRating(enumName);
        }
        serializedObject.ApplyModifiedProperties();
    }

    void DrawDamageRating(string enumName) {
        SerializedProperty damageRatingProperty = GetDamageRatingProperty(enumName);
        SerializedProperty valueProperty = damageRatingProperty.FindPropertyRelative("value");
        EditorGUILayout.PropertyField(valueProperty, new GUIContent(enumName));
    }

    SerializedProperty GetDamageRatingProperty(string enumName) {
        SerializedProperty damageRatingsProperty = serializedObject.FindProperty("damageRatings");
        for (int i = 0; i < damageRatingsProperty.arraySize; i++) {
            var damageRatingProperty = damageRatingsProperty.GetElementAtIndex(i);
            var nameProperty = damageRatingProperty.FindPropertyRelative("damageTypeName");
            if (string.Equals(enumName, nameProperty.stringValue)) {
                return damageRatingProperty;
            }
        }
        // Didn't find in array, so add it:
        damageRatingsProperty.arraySize++;
        var damageRatingProperty = damageRatingsProperty.GetElementAtIndex(damageRatingsProperty.arraySize - 1);
        damageRatingProperty.FindPropertyRelative("damageTypeName").stringValue = enumName;
        return damageRatingProperty;
    }
}

I just typed this into the post, so no guarantees against typos.

Also, you might want to clean up obsolete entries in case you end up deleting enum values.

Thanks for the suggestion. I’ll try it.