How to do visual debugging & editing using gizmos in Unity/C#

Let’s see how to use gizmos to create our own tools and improve the debugging/editing of our game data!

🚀 Find all of my Unity tutorials on Github!

This article is also available on Medium.

This tutorial is available either in video format or in text format – see below 🙂

Download the complement Unity assets (a more advanced HeroDebugger.cs script)

What is tooling? Why is it important?

You know how, sometimes, you just wish you could see a certain value while your game is running? Like the healthpoints of a unit, or the number of buildings a player has, or the CPU stats during this critical piece of code?

All of this data is not for the player but for the developers and the designers: it’s meta-data or debug info that won’t be shipped into the finished game but is crucial to checking all the systems in your game work as intended.

There is a specific subdomain of game development that specially focuses on making interfaces and consoles to monitor this type of info, called “tooling”. Because they create tools.

Those tools aren’t always pretty, but that’s not the point. The point is to show data in an intuitively readable manner so that the people who work on the game can analyse it easily and potentially find or fix bugs.

The tools can take various forms, from just an in-game console to a full-fledged dynamic inspector for your scene game objects. Actually, you can think of Unity’s editor windows as sort of powerful built-in tools… except that they’re (obviously) generic and cannot be exported during your dev builds.

This means that if we want to analyse some data that is very specific to our game, and/or if we want to see how it goes when we’re in a build of the game, we’ll need to make our own tools.

Note: I showed a little example of some in-game custom tooling for debugging my behaviour trees in my series on how to make a RTS in Unity 😉

Warming up: drawing a few gizmos

Showing a simple cube

To begin with, let’s see how to create some basic gizmos in our scene view. Gizmos are little shapes and visual aids that you can draw in your scene view to help with debugging. You have some for the camera or the directional light in the template scene by default, but you can also add your own using the OnDrawGizmos() or OnDrawGizmosSelected() functions.

To create our own gizmos, let’s just a little script in our project, called GizmosExample, and put it on an empty game object in the middle of our scene. Now, let’s edit this script and clear everything that’s inside. Because instead, we will want to use the OnDrawGizmos() method.

Ok so – in this function, we can use the Gizmos module (built-in into the Unity engine) to create various shapes in our scene. Here, if I look at the autocomplete that my IDE offers, I see that I can create a cube, a line, a sphere and lots of other stuff:

For now, let’s start with a basic cube. Gizmos.DrawCube() requires two parameters: the position to create the gizmo at, and the size of the cube to show. I’ll start with a basic world origin position (i.e. Vector3.zero) and a normalised scale of Vector3.one:

If I save my script and go back to Unity, once it’s done recompiling, you see that a little cube pops in the scene!

And once again: I haven’t run the game, it’s not playing or anything – actually, there is no scene to “run” per se. The gizmos are shown in edit mode, in your scene view. That makes it really easy and quick to debug things without having to wait for everything to start, and avoiding most of the dependencies issues.

It’s important to note that those gizmos are not actual 3D objects in your scene. So for example if I take my “Debugger” object and move it around, the position of the cube won’t change. That’s because we told the script to draw it at the world origin, and it only has this info. So it’s not like parenting children to an object: the gizmos are always drawn at the position you give in your C# script.

But anyway: we just created this “pseudo-object” with just one line of code in one specific function – so you can already the power of this debugging system: it’s quick to code and to test, and it has most of the things you will need ready-made and already accessible 😉

Adding a sphere and changing its colour

Ok, let’s jump back into our code and try to create a sphere this time. For this, we’ll use Gizmos.DrawSphere() and pass it a position and a radius.

But I’m actually going to offset both the sphere and the cube a bit from the origin point so they don’t collide with each other, and I’ll shrink them down a bit to better separate them visually:

I can save this and, back in Unity, I now have a little sphere on the right of my cube! 🙂

However, something that can be quite nice for debugging is to have some colours to differentiate your gizmos. This is really easy to do in our C# script: we just need to assign the Gizmos.color variable to a given colour. I’ll go for a basic full red tint:

And now, my sphere is red!

But you have to be careful, though: from that point on, everything you draw in your OnDrawGizmos function will use this same red colour. So for example if I duplicate my DrawSphere and offset it a bit, I will have 3 objects: my cube and my 2 spheres; but the 2 spheres will be red!

If I want to go back to white, or use another colour, I have to explicitly set the value of Gizmos.color again.

Making our gizmos use dynamic properties!

Now, another important thing with OnDrawGizmos() is that it is interactive: just like the Update() method in a usual Unity C# MonoBehavior script, it’s going to be called again and again by the engine. So we can actually make our debugger dynamic and react to changes!

Let’s see how this works by adding a little parameter to our script, a simple float variable called cubeSize. We’ll also add a custom attribute to this field to show it as a range between 0 and 1 (this way, we’ll get a little slider in the Inspector instead of a basic input field). Then, in our OnDrawGizmos() method, we can simply use this value in our DrawCube() call to set the size of the gizmo in the scene:

If I save my script and go back to Unity, you see that I have a new variable in the Inspector of my “Debugger” object that shows a slider from 0 to 1. And if I change the value, my cube just scales up and down accordingly and instantly!

Using handles for more advanced debugging

But if you want to build more advanced visual debuggers, chances are those gizmos will soon limit you too much. So, if cubes and spheres are not your cup of tea, you can dive into Unity’s editor handles and get even more crazy debuggers!

To access those objects, we just have to import another package in our script, the UnityEditor package. This package contains various utilities for editor tooling, like the handles are some base classes to make your own custom editors – we’ll talk about this in a sec:

So now that we have this package, if I try and type in Handles, you see that, once again, the autocomplete offers quite a lot of choice!

For example, we can draw a very basic circle using the Disk() utility. We just pass it a rotation, a position and a few other options, and we get a little white circle in our scene!

If we want to change the colour of our debugger, it’s just like with the gizmos except that we need to set the Handles.color property instead of the Gizmos.color:

We can even show up more complex geometries, like a nice Bézier curve.

Suppose we have 4 points that we store in a public array of Transforms. We can then combine gizmos and handles to first display a little cube at the position of each point, and then draw the bézier curve that goes through these points:

When I go back into Unity, I get some errors in the console because I haven’t assign my points yet. So let’s create 4 empty objects, rename them properly, and then drag them to the Inspector of my “debugger” object. Once the 4 slots have been filled, you see that little cubes pop in the middle of the screen!

Now, if I drag the objects around, the debug gizmo will follow and the Bézier curve will eventually show up. Sweet, right? 🙂

A concrete use case: debugging and editing our hero manager data visually!

Ok: now that we know how the gizmos system works, let’s actually use this to make some of our data more easily editable. We’ll take a common example in game dev: debugging and setting a value on a character manager.

Let’s say we have a little buddy in our scene that’s our hero avatar, shown as a capsule, and a bunch of enemies around it (the little blue cylinders).

We want to set how large the field of view of the hero is. So, basically, we want to tweak this “FOV” value so it feels right in the scene. The problem is that, for now, it’s just about guessing randomly what the best value could be – we don’t have any visual cues for what the right amount may be! And, in my opinion, it can be quite hard to intuitively get the scale of things in Unity…

But what if we could modify this FOV visually? What if we had a little handle we could drag around to set the FOV value? Then we could easily visualise it and insure that our FOV property is set to a valid value!

Well – we can actually solve this issue using gizmo handles and some custom editors 😉

Preparing the data

First, let’s make a very simple class to represent our hero: the HeroManager. This class will contain our actual game data, the data we want to visualise and modify thanks to our custom tool. This script will only contain just one public field, the float FOV value we want to manipulate:

I’ll just add this script to my “Hero” object. Of course, I have my FOV field displayed in the Inspector automatically by Unity, and I can tweak here if I want. But that’s not the point! 😉

Creating our own Unity editor

The next thing we need to do is create a custom editor for our HeroManager class. This will be a special type of Unity script, an editor script, that is not used in-game but by the editor itself to modify and improve the way some data is displayed in the Inspectors, windows and scene view.

Something crucial is that all editor-related scripts have to be placed in a specific folder in your project: you have to create an “Editor” folder at the root of your assets, and place your script inside it. Note that your script can be in subfolders inside this “Editor” folder if you want – but the important thing is that it is in this “Editor” sub-hierarchy!

So I’ll just create a HeroDebugger script, clear everything in it and change its parent class from MonoBehavior to Editor. This tells Unity that this script should be used by the editor instead of the running game. Note that for this class to be available, you once again have to import the UnityEditor package:

And before coding the class itself, though, we actually need to tell it what type of object it will be working on, which data type it is an editor for. This is done by adding a CustomEditor attribute above the class and passing the type to edit – in our case, that’s the HeroManager:

This time, the function we’ll define is the OnSceneGUI() function: this is called when the scene view is rendered to optionally show some additional user-defined GUI elements or even do some mesh editing. In this method, we can re-use the same editor utilities we saw before, so for example we can set the colour of our handles or our GUI, and we can even draw some circle at the origin point with a given radius, like this:

In the end, this circle will be our FOV display:

But, of course, we don’t want it to be drawn at the origin point, and we want its radius to depend on the current value of the FOV field in our HeroManager class instance!

So, first, we need to get a reference to our HeroManager object, the one that this editor is editing. Unity actually provides us with a reference to this object via the inherited variable called target. But this is an object: that’s the lazy C# type that can stand in for anything and then be converted back to your original data type using unboxing. So we need to transform it to a HeroManager variable by casting it explicitly:

And now, we can access the hero position and its current FOV value.

So let’s get this position and use it in our DrawWireDisc() call, along with the transform up vector and the FOV value for the radius. We can even improve our debugging tool by also showing the FOV value with a small text handle that is placed a bit outside the circle.

Note: here I’m using the ToString optional parameter to specify the format I want for my string – in this case, I want floats with just one decimal.

If we save this and go back to Unity, we see that there is now an orange circle and label around our hero object that show the current FOV value!

If we move the hero, the gizmo will follow along because their position depending on the position of the object the editor is targeting – and if we change the value of the FOV in the Inspector, we see that the gizmos update directly and show us the new FOV radius.

This is already quite good!

Updating the FOV value with our gizmos

But there is one last thing we can do to make it really nice to use: we can make it so that there is a handle on the circle to modify the FOV value without having to go all the way to the Inspector on the right! 😉

Unity’s handles package has one specifically for that: the ScaleValueHandle(). It displays a little gizmo that you can drag around to update a single float value. It takes in a bunch of parameters like the current value of the connected variable, the position, the orientation, the scale and so on… And just like some GUI elements, it returns a value – the new value for the float variable it is watching. So we can simply reassign this updated value to the FOV field of our HeroManager target instance, and this will connect the handle to the variable:

Now, if I go back into Unity, I can grab this arrow on the edge of the circle and drag it inwards or outwards to modify the FOV parameter of my hero.

I now have a really user-friendly tool to update my FOV value and make sure it has a proper value based on my scene – and this is way more convenient that a simple input field in the Inspector 🙂

It’s really quick to code, but it can make a huge difference in designing and optimising your game, because it gives you immediate feedback and makes the info overall more readable. This can be particularly useful if you some game designers in your team that prefer visual tools…

A quick note about OnDrawGizmosSelected

Earlier, I said that you can use either OnDrawGizmos() or OnDrawGizmosSelected() to show gizmos in your scene view. The only difference between those two methods is that the second one will only populate your scene with the gizmos if you have selected the object that has the script.

This can be pretty useful if you have a scene with lots of debuggers:

Instead of showing everything, you can just replace your OnDrawGizmos() with OnDrawGizmosSelected() in your script. This will both increases the performance of the debugging and make it easier to focus on just the relevant data:

Conclusion

In this episode, we saw how to do some basic tooling in Unity – we saw how to use the gizmos and scene GUI to display or even interact with data in our objects, and we made a user-friendly visual debugger and custom editor for a basic float field.

🚀 If you want to see a bit more advanced editor customisation, you can take a look at the Github repository for a complement bundle where I share a script that allows you to pick the variable you want to debug and tweak it with your scene Gizmos… and even change the debug colour!

Now, it’s up to you to come up with more ideas of what we could debug in Unity using these tools 😉

I hope you enjoyed this quick Unity tutorial and the dual video/text versions. Feel free to react in the comments and tell me if you like this new format — and of course, go ahead and share your ideas for future topics you’d like me to make Unity tutorials on!

Leave a Reply

Your email address will not be published. Required fields are marked *