Automate the boring parts
date
Sep 1, 2023
type
Post
year
slug
automate-the-boring-parts
status
Published
tags
Unity
Talk
EditorWindow
summary
A practical guide to building your own helpful tools in Unity (Write-up + Slides)
This is a write-up of my talk at NZGDC 2023 → ▶️ Slides

Intro
No matter how exciting the project you’re working on - it will inevitably contain dull, repetitive tasks. Assigning items to lists, sifting through endless amounts of assets, finding specific bits and pieces in the hierarchy - And what’s worse is that some of those boring tasks require your full attention and are even pretty exhausting to do! So you wear yourself out by doing something that could just as well be done by a monkey.
Well, I think we want to use our brain power on the important stuff instead. On the things that make a difference for our game! So whenever we find ourselves in the face of a boring task - let’s take a minute and see if we can write a small reusable tool to automate it!
Guiding Principles
I’ve been thinking about what’s been the most useful to me over the years and I’ve narrowed it down to these guiding principles: Convenience, Speed, Clarity - each one is good, if you manage do all 3 at once you’re golden.
Convenience
Nothing important should be more than a click or a shortcut away!
- This can be as simple as a window with shotcut buttons to your most often needed folders and objects.
- Or a menu item item that does something convenient for you
It doesn’t have to be pretty, some of these things are just for you.
- Or a window with buttons for aligning selected objects. Align them, space them out.

- Or this window - I got the idea from a handy little feature in Modo. If you’re tweaking values, then you don’t want to go sift through the hierarchy and jump from one thing to the next again and again. With Channel Focus you can add individual channels from different objects and tweak them easily, as well as monitor their values. But most importantly you can tweak at utmost efficiency! No time wasted, all your focus on the task at hand!

Speed
Save time (and your mental health) by automating things you have to do again and again.
Over the years I’ve taken several attempts to find a more general solution to the problem of having to do boring, repetitive stuff - the best one so far is BatchProcessor - Often times you have to find 20 little things in a scene or want to clean up and rename a few things and it’s always tedious. So I tried to build a general purpose tool to help with all that.

BatchProcessor lets you search for items, then apply “processors” to the resulting list of objects. So for example you could search for all UI elements in a specific colour and change it. Or search for all objects called Column with a boxCollider that’s less than a meter high and rename and number them to Small Column 1,2,3, etc.
Clarity
Make it easy to see what’s going on, what’s missing, etc. (Custom Inspectors, custom setup tools, etc.)
- For my long-time side-project Synthspace I built a custom Editor Window that makes setting up new modules easy. It guides me through the process, shows me what’s still missing and wherever possible offers a way to solve it or at least shows a shortcut to where my attention is needed!
But let’s get to it, let me show you how to build some useful bits and pieces!
What can we do in Unity?
What can we make, what can we customize?
As it turns out - pretty much everything.
We can create custom Editor Windows, Wizards, Custom Inspectors, add menu items, context menu options, create custom Scene Tools, draw lines and place gizmos in the scene view, we can add Settings, hook into asset importing and the build process, we can create custom previews, manipulate selections, etc., etc.
Everything that’s non-visual is just an Editor script and all you need to do is figure out what Editor API to hook into.
Everything that’s visual can be done with either IMGUI or UI Toolkit
The interface of the Unity Editor itself is done with IMGUI and UI Toolkit, so it’s quite easy to expand.
Basics
So what’s an Editor Script? In Unity there’s a fundamental difference between “normal” scripts and “Editor” scripts.
To make a script an Editor script you simply put it in a folder called “Editor” (you can have multiple of those all over your project)
Editor scripts
- won’t be included in builds
- can use stuff in the
UnityEditor
namespace!
A word of warning: nothing prevents you from using Editor-only APIs in normal scripts, but your builds will fail.
Menu Items
Simplest example: Let’s make a menu item that zeroes out the rotation of all selected objects!
We need a static class with a static function that we attribute with
MenuItem
Now we have a menu item under Tools and we even added a keyboard shortcut!
%
is for CTRL
/ CMD
#
is for SHIFT
&
is for ALT
Inside we step through all the GameObjects inside the current Selection, record an Undo step and change the rotation to zero. - note how this is one way of handling Undo - you record an object, then change it. We’ll see a different way later on.
Further Reading: Supporting Undo in Unity Editor scripts
Validate Function
There’s more things we can do with the
MenuItem
attribute. While we can’t change the name of a menu item at runtime, we can add a validation function that determines if our menu item should be enabled or disabled. In our case, it only makes sense to use our menu item if there are items selected, so let’s check if our selection is empty or not.
As you see, I created a function that returns true when we have selected at least one item. By giving it the same attribute with
true
for the isValidateFunction
argument, we turn this function into a validate function for our menu itemLastly we can determine where in the menu our function will be shown. If we add a number as the last argument - that will be used to figure out the order of things. If there’s a difference bigger than 10, it will add a divider in between menu items.
Here’s the finished script:

There’s more places where we can add menu items: If you want to add something to the context menu of a component, just do this:
Attributes and PropertyDrawers
So what was this
MenuItem
command in square braces really? Well, it was an Attribute! Attributes are classes that inherit from the Attribute base class. They can be used as sort of tags on other pieces of code. The cool thing is there’s a bunch of useful ones for customizing the looks of inspectors and we can make our own too!So even before we talk about IMGUI and UI Toolkit in a minute, we can already start customizing our inspectors!
Let’s say we have a very simple Spaceship class

Bit boring, you can’t really tell what’s what. Is anything wrong with this setup, is something missing or out of range? Is everything exactly as it should be? Who knows?
Let’s spice it up a bit with some attributes:

It’s better than before and adding some attributes only took a minute!
Custom Attributes and PropertyDrawers
Did I mention you can make custom ones too? Here’s one I’ve made that I find immensely useful: it’s called
Highlight
. Custom Attribute
This is the
HighlightAttribute
class, deriving from PropertyAttribute
It does nothing except offer a few constructors to fill its two variables
color
and highlightOnlyIfNull
Custom PropertyDrawer
The second piece of the Puzzle is a
PropertyDrawer
- When I first heard about this class I struggled to understand what it was for. No it’s not a drawer you put properties into, no, it draws a property.This one needs to be in an Editor folder!
Note how it’s got an attribute telling Unity that this is a custom property drawer for the
Highlight
attribute and how it derives from the PropertyDrawer
class.Most of the code is actually spent trying to figure out if the property is null or zero or empty or whatever.
Now watch what happens if we add this to the
BoosterParticles
field in our Spaceship
class with the colorOnlyIfNull
option:

It goes red when the field is empty - Now I can tell if something important is missing!
Custom UIs - IMGUI vs UI Toolkit
There are 2 UI systems we can use:
Immediate Mode GUI (IMGUI)
IMGUI has been around since Unity 2.0. It’s a nice and simple way to build nice and simple interfaces. If you try to build something more complex, it’s possible, but be prepared for tears.
It’s called Immediate Mode because you code layout and functionality all in the same script.
IMGUI only works in special places though (OnGUI for runtime, OnInspectorGUI for inspectors, OnGUI for EditorWindows) because it needs to look at the same code from multiple angles:
- First it runs a layout pass that figures out the sizing and positioning of all elements
- then it handles all events that have happened during the previous frame
- and finally it does a repaint pass where it actually draws everything onto the screen.
It’s simple to use. If you want a button, you write :

The
Button
function returns a bool, so if you want your button-click to do something, just wrap it in an if
:
Note how the
GUILayout
contains all the things you can use at runtime, but EditorGUILayout
contains a whole lot more for use only in the Editor! 🌐 → Unity Docs on EditorGUILayoutYou can do basic layouting by wrapping things in
GUILayout.BeginVertical
and GUILayout.EndVertical
, etc.

UI Toolkit
UI Toolkit is the new kid on the GUI block and based around web development paradigms. It’s a retained mode toolkit and based on UXML markup and USS style sheets. It’s great for more complex projects, but it’s more unwieldy right out of the box. Where IMGUI usually allows you to have everything in one compact script, with UI Toolkit you’re usually looking at least at a longer script and a UXML file. On the positive side, Unity has been working on tooling for a few years now and the most useful thing that’s come out of that is the UI Builder - a graphical drag and drop way of creating a UXML UI.

Then you just have to awkwardly bind it to your functionality and you’re good to go!
It’s all a bit awkward in my opinion, but then again all web development is a bit awkward, so…
Custom Inspectors
Let’s make some custom inspectors for a simple class!
I want to track the health of an Entity - player, monsters, NPC, whatever - so I made a simple class for that.
We have Max Health, Current Health and some ways to access those plus ways to apply damage or heal as well as resurrect the entity.
Now what I want to do is add some debug buttons
IMGUI Inspector
We start by making an Editor class that derives from
Editor
and add the CustomEditor
attribute and tell it which class we’re making a custom editor for - in this case: for the class Entity
.
In there we override
OnInspectorGUI()
and inside there that’s where we can go wild with IMGUI code.A first step would be to simply draw the default inspector with
DrawDefaultInspector();
and add our custom buttons at the bottom.But before we do that we need to know that we’re provided with 2 very useful things here:
A
target
object that contains a direct reference to the instance of the class that our custom inspector is shown for.And we get a
serializedObject
for the same instance. (A serializedObject basically holds all the serializedProperties of the instance. It’s a generic way of editing serialized fields on Unity objects, more on this in a bit! Or check out this post here: Supporting Undo in Unity Editor scripts)Ok. Draw Default Inspector, add buttons:
Note how I cast the target to
Entity
, then I can use it to call it’s methods from the Buttons!
Now I want the buttons to Display next to each other, so I wrap them in
GUILayout.BeginHorizontal()
and GUILayout.EndHorizontal()
- remember how the layouting pass will run through and figure out the positions of everything?And I add a bit of logic to make the buttons be disabled if we’re outside play mode, I make sure Undo is handled and switch the two buttons out for a single Resurrect button if the entity is dead.
If we wanted to draw the entire contents ourselves we could do that as well of course - I’m adding a slider (yes! that could have been done via an attribute in the Entity class!)

UI Toolkit Inspector
Let’s build the same thing with UI Toolkit!

Create the UI in UI Builder - select the canvas and set it to Editor Extension Authoring, then you get access to all the Editor-only elements and can select the Editor Theme at the top of the viewport.
Fill in Binding Paths for Controls
Create an Editor script deriving from the Editor class and add the
CustomEditor
attribute
To get our UXML in we need to add a field of type VisualTreeAsset that we can assign the file to in the inspector of the script file.
And instead of OnInspectorGUI, we override a different function:
CreateInspectorGUI
We clone the UXML into the root, query our buttons and make them do stuff:
Basics are done! Now let’s spice it up and make it show the resurrect button if dead and disable everything while not in play mode:

Done! Looks the same as the IMGUI one, but for simple stuff like this maybe a bit overkill, because the script is noticeably longer and we need a separate UXML file, so I’d say IMGUI wins this one, but this is about to change as we continue and make custom EditorWindows…
Custom EditorWindow
Editor Window (IMGUI)
Let’s build an editor window for the little spaceships prototype! Wouldn’t it be nice to have a little dockable window that gives us all the information for what’s currently going on? A list of all the ships with the most important controls for tweaking, and a list of all the players?
What we need:
- Static class deriving from
EditorWindow
- Static function with
MenuItem
attribute to open the window viaGetWindow
- Add our custom UI in
OnGUI

Now we’ve got an empty window. Let’s add some content!
First we need to find all relevant things in the scene, so

A bit more tweaking of sizes with
EditorGUIUtility.labelWidth
and GUILayout.MaxWidth()
and a bit more work to add current Players and it looks like this:
And yes - I could have also made a version of this that ran in the game view - that would have looked like this:

And in that case the buttons would not focus an object, but switch player control to a different ship. (Because we can’t use any Editor functionality here)
EditorWindow (UI Toolkit)
Let’s build the same thing with UI Toolkit!
Again we make a class deriving from
EditorWindow
and add a static function + MenuItem
attribute to open the window.BUT now we’re using
CreateGUI
instead of OnGUI to add our window UI.
Let’s make a UXML UI in UI Builder and bring that in…

I create the UI for a single spaceship and saved it as a UXML file.
Then I add a field where we can assign the UXML file we created and clone the UXML tree into a
VisualElement
and add that to the rootVisualElement
:
I add a way to find all the spaceships in the scene, and add a copy of the UXML tree for each one of them.
Then bind the
Slider
to the Spaceship
(since I set up the Binding Path in UI Builder, it will find the correct field on there) and bind the drag FloatField
to the Spaceship’s Rigidbody

I add a
Foldout
by turning the VisualElement
that we add everything to with a Foldout
:

For the Players, I create a second UXML file with the UI for a single player

Add a second field and assign the second UXML to that

Clone the player UXML into the tree for each player, bind it to the relevant things:

Done!

This should get you started on your journey to making your own useful tools in Unity. Let me know what you come up with!