28 May 2025

How to execute methods from the Godot inspector

Button at the inspector
Button at the inspector
A few days ago, I published an article explaining how to activate method execution from the inspector in Unity. We saw the possibility of using an attribute that generated an entry in an editor menu, and also how to create a custom editor so that the component inspector would show a button to activate the method.

Can the same be done in Godot? Well, until very recently, no. There wasn't an easy way to add a button to the inspector without developing a plugin and without the result being debatable. In terms of GUI customization, Godot still has a long way to go to be on par with Unity.

The [ExportToolButton] attribute 

However, Godot recently added a new attribute, @export_tool_button, and its equivalent in C# [ExportToolButton]. This attribute allows exporting a Callable field to the inspector and displaying it as a button. When the button is pressed, the method pointed to by the Callable is activated.

Let's look at an example in Godot C#. Suppose we have a ResetBoxManager method in our script:

The method we want to activate by pressing the button
The method we want to activate by pressing the button

What the method does doesn't matter. It's just an example. I show a screenshot of its content so you can see that the declaration and implementation of the method are nothing special. And now the button. To declare it, you just have to decorate a Callable field with an [ExportToolButton] tag.

Button declaration with [ExportToolButton]
Button declaration with [ExportToolButton]

Between the parentheses of the attribute, we will put the text we want the button to display. On the other hand, in the screenshot, you can see how to initialize the Callable. I called the field ResetButton (line 107) and initialized it with a new instance of Callable that points, by its parameters, to the ResetBoxManager method of that same class (hence the "this"), as can be seen in line 108.

With that, your inspector will show the button in the place that would have corresponded to the field, and when you press it, the linked method will be activated. You have a screenshot of how it looks in the image that opens this article.

Conclusion 

As you can see, the [ExportToolButton] attribute makes it really easy to add buttons to your inspectors. It combines the simplicity of the [ContextMenu] attribute we saw in Unity, with the visual appearance of its custom editors. With this, you can take a step forward in providing your inspectors with functionality that speeds up development and facilitates debugging your projects.

25 May 2025

How to execute methods from the Unity inspector

Cover image of the article
Unity is one of the most popular tools for game development, thanks to its flexibility and intuitive visual environment. One of the most useful features of Unity is its inspector. The inspector is a window in Unity that shows the properties of the components of a selected GameObject and allows us to adjust them. For example, if a GameObject has an associated script, the Inspector will show the public variables defined in that script, allowing you to modify them directly in the editor. However, what many novice developers do not know is that you can also configure the inspector to execute specific methods of your scripts, either to test functionalities or to configure more efficient workflows. In this article, I will explain how to execute methods from the Unity inspector in a simple way, a technique that can save you time and facilitate the configuration and debugging of your project.

The [ContextMenu] attribute 

A direct way to execute methods from the Inspector is by using the [ContextMenu] attribute. This attribute adds an entry at the end of the script's context menu in the inspector, allowing you to invoke methods with a single click. The context menu is the one that appears when you right-click on the component's name bar or the three dots in the upper right corner of the script in the inspector.

Context menu of a script in the inspector
Context menu of a script in the inspector

If you decorate the method you want to activate with this attribute: 

Example of using the attribute
Example of using the attribute

The entry will appear at the end of the context menu, with the text you have included in parentheses in the attribute. 

Resulting context menu
Resulting context menu

Creating a custom editor 

The previous option is the quickest to implement, but it may not be the most convenient as it involves two clicks to execute the method in question.

Another alternative, more visual, but more laborious, is to include a button in the inspector to activate the method. To do this, you have to create your own editor that shows a custom view of the component in the editor.

Let's analyze the simplest possible example. Suppose we have a MonoBehavior script called BoxRangeManager, with a method ResetBoxManager() (the one from the previous screenshot) that we want to activate. To create an editor that shows a custom view of BoxRangeManager, you have to create an Editor folder inside the main Assets folder. In the Editor folder is where you should put all the scripts dedicated to customizing the Unity editor. It is very important that these scripts do not end up in the usual Scripts folder, otherwise, you may have serious compilation problems when you want to build the final executable of the game. Remember: game scripts in the Scripts folder, and editor customization scripts in the Editor folder.

Continuing with our example, once the Editor folder is created, you have to create a script like the one in the following screenshot:

The code of our custom editor
The code of our custom editor

The first notable thing about the previous code is that it imports the UnityEditor namespace (line 2). That is the first sign that your script should be in the Editor folder or you will have problems when building your executable package. Including the code in its own namespace (line 5) is a good practice, but not essential.

Let's get to the point: for a class to be used to implement a custom editor, it must inherit from UnityEditor.Editor (line 8); and for Unity to know which MonoBehaviour to use the custom editor with, you have to identify it in a [CustomEditor] tag that decorates the class (line 7).

From there, to customize how BoxRangeManager is displayed in the inspector, you have to reimplement the OnInspectorGUI() method of UnityEditor.Editor (line 10).

Our example is the simplest possible. We just want to show the default inspector and add a button at the end of it that activates the ResetBoxManager() method when pressed. So the first thing we do is draw the inspector as the default inspector would have done (line 13). Then we add a space so as not to stick the button too close to everything above (line 16). Finally, we add our button on line 22, passing as parameters the text we want to appear on the button and the height we want it to have.

The button returns true when pressed. Thanks to that, in lines 24 and 25 we can define the reaction when pressed. In that case, the first thing is to execute the ResetBoxManager() method we wanted (line 24) and then call the EditorUtility.SetDirty() method (line 25) to notify the editor that we have made changes in the component's inspector and force it to redraw it.

Note that the custom editor contains a reference to the MonoBehavior whose inspector it shows in the target field. You just have to cast to the class you know you are showing (line 19) to have access to its public fields and methods.

And that's it. You don't have to do anything else. Once Unity reloads the domain, the custom editor with our new and shiny button will be displayed.

Appearance of our custom editor
Appearance of our custom editor

Conclusion 

Executing methods from the Unity Inspector is a powerful technique to streamline the development and debugging of your projects. Whether using the [ContextMenu] attribute for quick tests or with custom editors, these tools allow you to interact with your code in a more dynamic and visual way.

Experiment with these options and find out which one best suits your workflow. The Unity Inspector is much more than just a property editor!

18 May 2025

Volumetric sensors with dynamic dimensions in Unity

Creating a volumetric sensor in Unity is simple: you add a Collider component to a Transform, configure it as a trigger, shape the Collider to define the sensor's range, and add a script to the Transform that implements the OnTriggerEnter and OnTriggerExit methods. The Collider will activate these methods when another collider enters or exits its range, respectively.

That's all, and it usually suffices in most cases, but there are others where we need to define the shape of the volumetric sensor in real-time, during the game's execution. Imagine, for example, that you want to equip a mobile agent with a volumetric sensor to detect obstacles that may interfere with its path. Normally, you would place a volumetric sensor in the shape of a box in front of the agent, and this box would extend forward along a distance proportional to the agent's speed. If the box is too short, obstacles may be detected too late for the agent to avoid a collision. If the box is too long, the agent may react to obstacles that are too far away, which would be unrealistic.

A mobile agent with a volumetric sensor to detect obstacles
A mobile agent with a volumetric sensor to detect obstacles

If the agent always maintains a constant speed, it will suffice to manually set the sensor's size when designing the agent. But if the agent varies its speed depending on its behavior, a single type of sensor may not be suitable for all possible speeds. In such cases, we could equip the agent with several sensors of different sizes and activate one or another depending on the speed range the agent is in. However, this solution will be very complex and difficult to scale if we end up changing the agent's speed range. It is much better to modify the sensor's size during execution and adapt it to the agent's speed at each moment.

I will explain how I do it with a BoxCollider2D. I'm not saying it's the best way to do it, but it's the best way I've found so far. You will find it easy to adapt my examples to other collider shapes and use them as a starting point to find the mechanism that best suits your case.

A BoxCollider2D allows changing its size through its size property. This consists of a Vector2 whose first component defines the width and the second the height of the box. We can change the value of this property at any time, and the collider will adapt its shape to it. The problem is that the BoxCollider will remain centered and grow in both directions of the modified component. If we have a case like the one in the previous capture, what we want is for the collider to grow forward when we increase the speed, and not for the collider to grow also towards the rear of the agent.

The way to solve it is to modify the dimension we are interested in, in the case of the agent in the capture it will be the height of the box, and at the same time displace the box, manipulating its offset, so that it seems to grow only on one side. In the example at hand, to make the sensor grow, we would increase the height of the box and at the same time displace its offset upwards to keep the lower side of the box in the same position and make it seem to grow only on the upper side.

We want the collider to grow only on one side
We want the collider to grow only on one side

Based on the above, I will show you the code I use to generalize the different possible cases for a box. For a BoxCollider, the possible size modifications are those of the enum in the following capture:

Possible growth directions for a box
Possible growth directions for a box

The options explain themselves: "Up" means we want the box to grow only on its upper side, "Down" on the lower side, "Left" on the left side, and "Right" on the right side. "Symmetric" is the default behavior according to which, when changing the height, the box would grow both on its upper and lower sides.

The point is that when you increase the size of a box in one of its dimensions, this increase is evenly distributed in a growth of both sides of that dimension. For example, if you increase the height of a box by 2 units, you can expect the upper side to rise by one unit and the lower side to drop by another. Therefore, if you wanted the box to appear to grow only on the upper side, you should keep the lower side in the same position by making the box rise by one unit.

The way to generalize it is that the box must move half the size increase in the growth direction we have marked.

How to calculate the box's movement vector
How to calculate the box's movement vector

The box's movement vector can be obtained from a method like the previous one (GetGrowOffsetVector). In the case of our example, where we want the box to appear to grow on the upper side and the lower side to remain in its position, the growDirection would be "Up," so the method would return a Vector2 with the values (0, 0.5). Note that I have defined OffsetBias as a constant value of 0.5. This vector will then be multiplied by the box's growth vector, which will give us the box's displacement.

The growth vector is the resulting vector from subtracting the new box size from the initial size.

Calculation of the growth vector
Calculation of the growth vector

Therefore, every time we want to change the box's size, we will have to calculate the growth vector and multiply it by the box's movement vector to obtain the new box offset so that it appears to have moved only on one side.

Method to change the box's size
Method to change the box's size

The SetBoxSize() method, in which I implement the above, cannot be simpler. In lines 153 and 154, I reset the box to its initial size (1,1) and its offset to (0,0). Since the new size is set immediately afterward, the reset is instantaneous and not noticeable.

Then, in line 155, I execute the GetGrowOffsetVector() method to obtain the box's movement vector. And in line 156, I obtain the growth vector by calling the GetGrowVector() method. Both vectors are multiplied in line 158 to give the new box offset. Note in that same line, 158, that I use the initialOffset field (of type Vector2) to define a default box offset. This will be the offset the box will have when no movement has been applied.

Also note that I use the boxCollider field to manipulate the collider's properties. This field has a reference to the collider. You can obtain this reference either by exposing the field in the inspector and dragging the collider onto that field or by using a call to GetComponent() in the script's Ready().

If you include the previous methods in a script and make it expose public methods that end up calling SetBoxSize(), you will be able to manipulate the collider's size in real-time from other game scripts.

And with this, you have everything. It's quite simple once you have it clear, but if you start from scratch, it can take a while to figure out how to do it. I hope this article has saved you that time and that you found it interesting.

15 May 2025

Course "Beat'em up Godot tutorial"

Some time ago, I completed the "Beat'em up Godot tutorial," but I hadn't found the time to write about it until now.

This is a 20-episode video tutorial available for free on YouTube, taking roughly 10 hours to complete. In it, the author guides you through the process of creating a beat'em up game, similar to classics like Streets of Rage or Double Dragon. As I understand, the game was originally developed for a Game Jam and turned out so polished that it was an ideal candidate for a course.

The content starts from the basics, making it perfectly suitable for those looking to get started with Godot. However, it also dives into more advanced concepts after the initial learning curve, so it will also appeal to intermediate learners or those simply looking for a Godot refresher.

It begins with fundamental concepts like shaping characters, their animations, and movements. Then it covers the damage system, based on hitboxes, which I found quite interesting as it’s a much simpler and more elegant system than the one I had used before. It also implements state machines for characters, built from scratch through code. While this was interesting, I felt it was a bit like reinventing the wheel. I would have preferred if the author had used Godot’s built-in state machine system via its Animation Tree. After that, the course moves on to implementing weapons, both melee and throwable, as well as other collectible items like food and health kits. I also found the way the author sets up the levels and the various enemy spawn points to be very interesting and original. Everything is highly modular and reusable. As for the GUI, music, and sound, it covers the basics, but a retro-style game like this doesn’t really demand much more.

Having taken several courses, read books, and worked on some projects, I can now clearly distinguish good practices and clean, organized development—and this course delivers. I did feel that using C# might have made the code even more modular, but the author makes good use of GDScript within its limitations. Godot’s node system inherently enforces high modularity and reusability, and combined with the lightweight editor, it makes game development quite straightforward, with very few moments of waiting or writing repetitive code. Since the game’s resources are publicly available, I plan to implement it in Unity to see how it compares to Godot.

Overall, the course is very engaging, and you get a high return for the time invested. In summary: a highly recommended course.