This post is sort of a follow-up on a previous post that aimed to accomplish a similar thing. If you want to you can read it first, however, I do generally prefer the solution that is presented in the present article.

Image 1.1: This is what we’ll be making today!

BLOODY HELL, ARE WE STILL DOING THESE?

So… Shortly after publishing this post I thought of another, possibly even cooler, but more importantly, even more useful way of making sure our public scene name strings match the name of a scene in the build settings.

Have you seen the default way that Unity draws enums in the inspector? They’re displayed as a nice dropdown that lets you select from all the possible enum names of that enum type (see image 1.1). In this post I’ll go over how to make something similar, but for selecting valid scene names (i.e. names of scenes found in the build settings)!

In case you didn’t see the last post, we’ll be making a custom PropertyAttribute paired with a PropertyDrawer to make the magic happen.

Image 1.2: What a nice dropdown!

DROP IT

Alright, so we all agree that dropdowns are a gift from above (😉), however, what might split the waters is whether we want to include the path to the scene as well. Showing the path, or at least some of it, can be useful if you have a lot of scenes split into different categories (and as such different folders in the project hierarchy), but if all you have is just a few (eg. Main Menu Scene, Game Scene, and Credits Scene) it might be nicer with a more simple view. That’s why this time we’ll experiment with overloading the constructor of our custom PropertyAttribute!

Let’s quickly look at what we’ll end up with in terms of the attributes we will put on our public strings (Snippet 1.1). As you can see, we’ll get the ability to overload the main attribute constructor with a bool that signifies whether we want to show the path to the scene as well. Quite simple, yet very flexible.

This code results in what you see in Image 1.1 at the top of the post.

Snippet 1.1: What we’ll be writing in our MonoBehaviors.

THE PROPERTY ATTRIBUTE

This one is almost as simple as last time, however, this time we need to also overload the default constructor to take the bool that will decide whether to show the path or not. I’ll also default the value to False , however you can default it to True if you would generally prefer to not include the path in the dropdown.

Since we want to keep the ability to simply write [SceneNamePicker] we have to also create the default constructor (just keep it empty), or we will get nasty errors in the console.

Snippet 1.2: Overloading the constructor to diversify uses of the attribute

And that’s it for the attribute class. Again, most of the magic really happens in the PropertyDrawer, which we’ll move on to now. Are you hyped yet?

THE PROPERTY DRAWER

After creating a new C# file and placing it in the editor we can begin fleshing out what we want our PropertyDrawer to do. Firstly, let’s make the class import the UnityEngine namespace, as well as inherit from PropertyDrawer. We’ll also define that this PropertyDrawer should take over the property drawing of whatever is tagged with the [SceneNamePicker] attribute.

Snippet 1.3: Outline of the desired actions in the OnGUI method

As outlined in the comments in Snippet 1.3 the agenda for the OnGUI() method is to find all the scene names (listed in the build settings), check if the current value of the string corresponds to one of those scene names, and of course actually draw the nice little dropdown. As always when working with SerializedProperties (of SerializedObjects), we wanna start by updating the property to include the latest changes, as well as end with applying any modifications we might do.

Since we include the possibility to exclude the scene path, the code has to branch if only a little bit. As you remember, the attribute has a showPath property that defaults to false, but we can’t see if the overloaded constructor was used or not, so we’ll start by grabbing a reference to the target attribute, which will allow us to check the value of the bool in the PropertyDrawer. We’ll also check the property.stringValue to check if it is valid or not, which we’ll do in the IsValidSceneName() method (we’ll get to in a moment). If it’s valid (meaning theres a scene with the same name in the build settings) we find the corresponding index in the array of valid strings and assign it to the selectedIndex variable. The reason we want to do this check (rather than just keeping the index consistent) is that if the order of the scenes in the build settings are ever reordered, we would end up with other scene names in our MonoBehaviours (which I think we can agree can only lead to a world of pain).
Finally, we use the EditorGUI.Popup() method to draw the nice dropdown, feeding it the property Rect, the nice display name of the property (eg. “MyProperty” becomes “My Property” in the Inspector), the selected index (which also draws a nice little checkmark next to the selected value in the dropdown), and the array of valid scene names that we get from the GetValidSceneNames() method that we’ll get to next.

Snippet 1.4: The final OnGUI method

Now it’s time to actually make the IsValidSceneName() and GetValidSceneNames() methods – let’s start with the latter.

Similar to the previous post we get the list of scenes with the EditorBuildSettingsScene.GetActiveSceneList() which takes an EditorBuildSettingsScene[] array that we get from the EditorBuildSettings.scenes property. This is where we branch the logic slightly to allow the different types of use (with or without prefixed path). If we don’t want to include the path, meaning we are only interested in the name of the scenes, we simply use the full scene paths to load the SceneAssets and get the ‘.name‘. Alternatively, if we do want to include the path we could choose to do nothing to the path string, however, at the least I’ve chosen to exclude “Assets/” from the path since it will be common to ALL scenes, as well as the “.unity” file extension (since we don’t really need to see it).

Snippet 1.5: The method used to get (and clean up) the valid scene names

Now that we got that out of the way, actually validating the scene name (given a string) is quite simple. We just loop through the array of valid scene names, comparing the input parameter. If we find a match we’ll return True , if otherwise we’ll return False .

CONCLUSION

So now we have that fancy lil’ scene name selection dropdown we saw earlier. I personally find this approach nicer than the method from the previous post, however now you’ll have two different types of attributes to use for your scene name selecting pleasure! As always you can copy-paste the source code from down below, or simply download this unitypackage to include the attributes in your project! Let me hear what you think, and feel free to share other cool uses of custom attributes here. Also thumbs up to those of you who get the Ashens reference in one of the headlines 😉!

SOURCE CODE

(Put this in a non-Editor folder)

(Put this in an Editor folder)