Manage lots of Enum choices in the Inspector

I’m writing a RPG, and to keep track of individual item types (ex: each weapon, each resource &c), I use an enum.

At the moment I have 90 or so entries, and so when I need to find a specific item type in the inspector, it’s a bit of a headache. The inspector supports searching by the first character (and only that), but that’s not that helpful

Is there a way of managing enum values in the inspector - such as being able to group them, or get a better search instead of going through the dropdown?

Using an enum might not be the best solution in your case. But I don’t know your system enough to judge.

Anyway, InspectorName attribute lets you group enum values.

public enum Item
{
    [InspectorName("Weapon/Melee/Sword")]
    Sword,
    [InspectorName("Weapon/Melee/Axe")]
    Axe,
    [InspectorName("Weapon/Ranged/Bow")]
    Bow,
    [InspectorName("Weapon/Magic/Wand")]
    Wand,
    [InspectorName("Weapon/Magic/Staff")]
    Staff,
    [InspectorName("Equipment/Helmet")]
    Helmet,
    [InspectorName("Equipment/Armor")]
    Armor,
    [InspectorName("Consumable/HealthPotion")]
    HealthPotion,
    [InspectorName("Consumable/ManaPotion")]
    ManaPotion,
    [InspectorName("Consumable/Food")]
    Food,
    Coin
}

188120-enuminspectorname.png


If you want the enum to be searchable, you’ll need more code:

// SearchableAttribute.cs in your Assets folder

using UnityEngine;

public class SearchableAttribute : PropertyAttribute { }

// SearchableAttributeDrawer.cs >>> IN AN 'Editor' FOLDER <<<

using System;
using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(SearchableAttribute))]
public class SearchableAttributeDrawer : PropertyDrawer
{
    private string search;
    private string[] options;
    private GUIStyle searchTextFieldStyle;

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        float height = base.GetPropertyHeight(property, label);

        if (property.propertyType == SerializedPropertyType.Enum)
            height = height * 2 + EditorGUIUtility.standardVerticalSpacing;

        return height;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        if (property.propertyType == SerializedPropertyType.Enum)
        {
            if (searchTextFieldStyle == null)
                searchTextFieldStyle = GUI.skin.FindStyle("ToolbarSeachTextField");

            if (options == null)
                UpdateOptions(property.enumDisplayNames);

            Rect searchRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
            DrawSearchBar(searchRect, label, property.enumDisplayNames);

            Rect popupRect = new Rect(position.x, searchRect.y + searchRect.height + EditorGUIUtility.standardVerticalSpacing, position.width, EditorGUIUtility.singleLineHeight);
            DrawEnumPopup(popupRect, property);
        }
        else
        {
            EditorGUI.PropertyField(position, property, label);
        }
    }

    private void DrawSearchBar(Rect position, GUIContent label, string[] allOptions)
    {
        EditorGUI.BeginChangeCheck();
        search = EditorGUI.TextField(position, label, search, searchTextFieldStyle);
        if(EditorGUI.EndChangeCheck())
            UpdateOptions(allOptions);
    }

    private void DrawEnumPopup(Rect position, SerializedProperty property)
    {
        Rect fieldRect = EditorGUI.PrefixLabel(position, new GUIContent(" "));
        int currentIndex = Array.IndexOf(options, property.enumDisplayNames[property.enumValueIndex]);
        int selectedIndex = EditorGUI.Popup(fieldRect, currentIndex, options);
        if (selectedIndex >= 0)
        {
            int newIndex = Array.IndexOf(property.enumDisplayNames, options[selectedIndex]);
            if (newIndex != currentIndex)
            {
                property.enumValueIndex = newIndex;
                search = string.Empty;
                UpdateOptions(property.enumDisplayNames);
            }
        }
    }

    private void UpdateOptions(string[] allOptions)
    {
        options = Array.FindAll(allOptions, name => string.IsNullOrEmpty(search) || name.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) >= 0);
    }
}

// In your code

[Searchable]
public Item Item;

this tool might help: