C# Editor GUI custom list type PopUp return string and not int

Hi,

Is there a way to create a popup selector for a custom list in Unity EditorWindow?

This is the code I currently have,

buildingsConfiguration.category = EditorGUILayout.Popup("Category", buildingsConfiguration.category, buildingsList.buildingsCategories, EditorStyles.popup);

buildingsConfiguration.category is intand buildingsList.buildingsCategories is the custom list class. The custom list class is non monobehaviour class.

UPDATE

After googling for sometime, I found out there isn’t a way to use a list directly. So here is my solution,

using System.Linq;

private string[] category[];

private void ReloadCategory()
        {
            category = null;
            category = buildingsList.buildingsCategories.Select(I => I.name).ToArray();
        }

//And within OnGUI
 buildingsConfiguration.category = EditorGUILayout.Popup("Category", buildingsConfiguration.category, category, EditorStyles.popup);

The reloadcategory is called onenable and also a option within the editorwindow to call it manually.

Though I am not entirely sure if this is a good idea. Cause I could remove a category within the list and add another one, and the script will never know it changed. (Or I could remove a category and that index number will be not found which could cause errors). My best option is no never delete any category once made.

Is there anyway I could make the popup return a string instead of int?

Well, i’m not sure if the question is more about how to make that Popup work properly or how to ensure data integrity for your inspected object. Of course indices into an array / List have the general problem that they don’t like reorder, insert in the middle and deletion as it will messup or break the proper link.

A common and neat solution to the integrity problem is to use ScriptableObjects as categories. In that case the object doesn’t store an index or a string but a serialized reference to your category object which is stored as asset in your project. Of course deleting such an asset would turn all references to it into null (“fake null”) references, but all other categories and objects wouldn’t even notice.

You could probably use Awake and OnDisable of each category object to automatically add / remove itself to / from a static list or a CategoryManager object.

When building the string array cache you might want to add an index field to each category object to indicate the “current” index. Of course when you mess around with the order or add / remove some they would be messed up. However since we have a cached array we can simply update that information. There are generally 3 situations:

  • The array length / number of categories stay the same but the list is messed up in some way. This could be due to a reorder, the same amount of add and remove at the same time or a rename.
  • The array is too short compared to the list of categories.
  • The array is too long compared to the list of categories.

Case 1 would be already covered when we simply copy the names over each time our GUI is called. Since the array already exists and the count is the same, no garbage is generated. Since strings are immutable reference types, copying the names into the cache array doesn’t generate garbage.

The other two cases would require you to resize the cache array. So you would simply first check if the list count and the cache array length are the same, if not, create a new array with the proper size.

Finally just loop through all your categories, copy the name over to the array and in turn set the index of the category objects.

When calling the Popup function you would simply use the cache array and the current index of your category. Of course the category could be “null” in which case you have to use something like “-1”.

When the method returns you would check the returned index for valid range (>=0 and