I’m convinced that one of the secrets to levelling up your Unity skills is to become very comfortable writing custom editor tools. Every project I’ve worked on in the past year has been made significantly better by building tools to automate repetitive or time consuming tasks.
For example, imagine you are working on a project which requires placing gems at even distances (like coins in Temple Run, or rings in Sonic). Placing all of these by hand isn’t a good use of anyone’s time, and making changes to these layouts sucks because moving a gem in the middle of a row means that everything after it needs to be adjusted as well.
A tool that automatically places objects at even spaces along a spline would not only allow you to get the objects placed faster, but make it way easier to make changes later. This post is going to show you the basics of how to put a tool like this together.
(there’s a unitypackage download at the end of this post if you just want the code).
The tool we’re building is fairly simple, but there are a few different parts we need to set up. We’ll cover these in order:
I could probably write a few blog posts just covering different spline creation algorithms, but thankfully the Unity wiki has us covered here. Head over there and grab the Interpolate.cs script. This will handle all the complicated parts of creating our spline for us. All that’s left for us is to define the inputs.
If you look at Interpolate.cs, you’ll find the method that we’ll be using to generate our splines:
So the inputs we need are an array of node positions (the initial control points that will define the shape of our spline), the number of slices (points placed between these initial nodes), whether or not we want our spline to loop and finally the GameObject we want to duplicate along the path.
However, none of the logic regarding what these inputs are should be put into Interpolate.cs, which means it’s time for us to start writing our custom tool class.
So as mentioned, the first thing our tool will need to do is provide inputs to the Interpolate class. So let’s set that up:
You can go ahead and set these up in the inspector if you want, although you won’t see anything yet. so perhaps we should also set up the gizmos to visualize the spline. Gizmos (for those who are unfamiliar with them) are objects which are drawn in the scene view but do not appear in your actual game. We’re going to be using the Gizmo api to draw our spline.
To write a custom gizmo for a component, you need to override the OnDrawGizmos method. Let’s start by drawing a sphere at every initial node point, so that we don’t need the Transform objects we’re supplying to have a mesh renderer attached to them. The code below allocates an array of Vector3s that isn’t really being used in this example, but we will be using this array later, so I’ve included it now to avoid needing to change code as we go.
If you switch back to the editor, and add a few empty GameObjects to the list of initialNodes, you should now have shiny wireframe spheres in the scene view to help you see what’s going on.
Great! Now let’s get on with the business of actually seeing our spline.
To do this, we need to create a spline on every call of the OnDrawGizmos method, and draw a line segment between each node on the newly created spline (we create a new spline on every call so that we can see the updates to the spline as we move the nodes in the scene view).
If you compile this, and throw a few control points into the inspector panel, you should be able to drag them around see something like this:
Although this looks cool, it really isn’t useful yet, which brings us to part 3:
The most common use case I’ve found for this type of tool is placing objects along the spline while setting up the scene (ie/ before runtime), so that’s what we’ll cover here.
I’ve found the most intuitive way to handle this is to write a custom inspector for the SplinePlacer class that draws a button that triggers the placement action. So lets do that now:
This code won’t compile yet, because we haven’t defined the PlaceObjects method in SplinePlacer, so go ahead and add an empty method with that name now. Once you’ve done that, throw this new inspector class into your Editor folder and let it compile. If you click back to your spline placer object it should look something like this:
Now all that’s left is to actually have PlaceObjects do something and we’re good to go. This gets a bit a hairy, especially because I’m duplicating a lot of code so that I can present a self contained method for this tutorial, but the algorithm is as follows:
And an implementation of this might look like this:
Once this code compiles, pressing the “Place Objects” button should populate your spline with the object you provided to be duplicated.
Depending on your needs, there are a ton of different ways to improve on this tool. One addition I’ve found useful is to bind a keyboard shortcut to the act of creating another initial node, adding it to the end of the list of nodes, and selecting it in the hierarchy. This simplifies the process of creating paths greatly.
Another option I’ve found handy in some cases is to automatically select all the spawned objects after placing them, allowing a really quick group edit of their components.
You may also want to write additional inspector buttons for doing things like deleting all spawned children, or serializing their positions, or any of a million other things that might make your specific use case better. There isn’t a “right” way to go about this, as long as your life is better when you’re done the tool.
If you’re running into any issues getting things to work, feel free to grab this unitypackage, which contains all of the code presented above. If you’re still running into issues, or you have tools of your own that you want to share, send me a message on twitter!