Debugging is a really fun activity, isn't it? Often we require some extra tools to aid in this process. Maybe by dumping a bunch of text into the screen or drawing some extra lines. This addon is meant to bring some little scripts to help with those.
Activating the "Debug Helpers" addon will automatically add the scripts into the auto-load list. The default name to reference them will be mentioned in the specific "sub-addon" topics. Nevertheless, if you prefer you can manually add those scripts to the singleton list instead of activating the plugin.
This script is meant to be part of the auto-load list, meaning that its functionality will be accessible from wherever in the code. Basically it provides a few functions to add/remove text into/from the screen using the
Label Control widget. Those are added into a panel that expands/shrinks according to the contents. This panel is, by default, black with some transparency set just so text is more easily readable. This color (and transparency) can be changed.
By default this script will be named
OverlayDebugInfo and it's the name that will be used throughout the rest of this topic.
Once the script is in the auto-load list, you can then easily use the functionality. Note that by default the panel is set to be shown, which will result in a tiny black square on the top left corner of the screen. From code you can control the visibility of the entire panel using
set_visibility() function, which requires a single parameter,
true to show and
false to hide. So, if you don't want the panel to be visible in you main menu (or anywhere else, actually), you can add this into the
There is also a "shortcut" function that you can use to toggle the visibility. This can be useful to be called from a key press event:
# Toggle the visibility of the overlay debug info panel OverlayDebugInfo.toggle_visibility()
When you want to add text to the screen, there are two options:
set_label(): adds a label to the screen, which must be associated with some ID, so you can then manipulate it or even remove.
add_timed_label(): add a label that will remain on screen during some time then will be deleted. Those don't require any ID.
Let see the
set_label() first. It requires two arguments, the label ID and the text that will be set into that label. That said, suppose you want a label that will display the position of a character, which changes during the game. Assume we have a variable named
character_position holding this information. Then we can call the function during the
Note that you don't have to first create a label with that name (
char_pos in this example). The script will take care of creating the Label object if it doesn't exist.
Now suppose you want to see some information being shown on the screen for a short amount of time, mostly because the value you want to check doesn't change too frequently (if at all), but you still want to verify if the value is correct. For that, there is the
add_timed_label() function, which also requires two arguments, the text and the amount of seconds the information will remain on screen.
For the next script, suppose you have one plant object that holds a
grow_stage property which isn't updated too frequently. You then want to check this value when you press a key and keep this information for only 2 seconds:
OverlayDebugInfo.add_timed_label("Grow Stage: %s" % grow_stage, 2.0)
With this, the label will be removed from the panel after 2 seconds.
After you have set a "permanent" label you can remove it, with the
remove_label() function. It requires a single argument, the ID of the label. So, going back to the character position example, we can remove that information with this:
You can clear all non timed labels at once like this:
The position of the panel can be changed, into "9 spots" by setting the vertical and horizontal alignment:
# Put the panel on the left horizontal alignment OverlayDebugInfo.set_horizontal_align_left() # Put the panel on the center horizontal alignment OverlayDebugInfo.set_horizontal_align_center() # Put the panel on the right horizontal alignment OverlayDebugInfo.set_horizontal_align_right() # Put the panel on the top vertical alignment OverlayDebugInfo.set_vertical_align_top() # Put the panel on the center vertical alignment OverlayDebugInfo.set_vertical_align_center() # Put the panel on the bottom vertical alignment OverlayDebugInfo.set_vertical_align_bottom()
With those, suppose you want the panel to be placed on the bottom-right corner of the screen. Those two can be called in sequence:
Finally, to change the color of the panel, there is the function
set_panel_color(), which requires a single argument, the color itself. Suppose we wanted to change the panel to white with 50% transparency:
OverlayDebugInfo.set_panel_color(Color(1.0, 1.0, 1.0, 0.5))
And that's all for this script!
As with the
overlayinfo.gd script, once this one is in the auto-load list, the functionality can be accessed.
By default this script will be named
DebugLine3D and it's the name that will be used throughout the rest of this topic.
To draw a line, there is the
add_line() function, which requires 2 arguments plus one optional. The first two are the global positions of the end points. Perhaps this should have been named
add_line_segment() but, really, this would become really tedious, right? The optional argument specifies the color of the line, which defaults to white. That said, suppose you have two positions stored in
Vector3 variables (
p2) and you want to draw a line connecting those two points using the red color:
DebugLine3D.add_line(p1, p2, Color.red)
Doing so will create a line that will be drawn during a single physics iteration frame. In other words, on the next update the line will be removed. This is done in this way because the idea is to show lines for things that do change frequently. With that in mind, if you want the line connecting those two points to remain more time on screen you either keep calling the
add_line() function as part of the
_physics_process() function or call the
add_timed_line() requires 3 arguments plus the optional color. The first two arguments are the end points of the line segment while the third one is the amount of time (in seconds) the line will remain on screen. So, let's add a green line that will disappear after 2.5 seconds:
DebugLine3D.add_timed_line(p1, p2, Color.green, 2.5)
There is one detail, this function returns a value, which is the "ID" of the created line. This ID can be used to manually remove a timed line. The thing is, if you specify a 0 (or negative) value as the amount of time, the line will remain there and will not be automatically removed. To have more control over when the line is to be removed, you can use
remove_timed_line(), which requires the ID returned from the
add_timed_line() function. So, you can use something like this:
var timed_line: int = DebugLine3D.add_timed_line(p1, p2, some_color, 0) # ... later, maybe even somewhere in the code, remove the line DebugLine3D.remove_timed_line(timed_line)
Godot will probably warn you about a return value that was ignored if you used the
add_timed_line() function without using what was returned. It's possible to append a comment to tell Godot you are aware of that and you don't want to be warned, like this:
# warning-ignore:return_value_discarded DebugLine3D.add_timed_line(p1, p2, some_color, some_time)
It's possible to disable the functionality of the addon (basically its processing) while still being able to access it. The idea here is to not clash too much with the game logic code (having to remove debug code then adding it back) all the time but also allowing the script to do nothing when disabled. Basically, you can the
set_enabled() function, which requires a single boolean argument:
# Disable the line3d processing DebugLine3D.set_enabled(false) # Or enable it DebugLine3D.set_enabled(true)
This can be called somewhere on the main menu script or during initialization of another auto-load script prior to exporting the project. Then any call to add debug lines will basically do nothing. You can check its state by calling
if (DebugLine3D.is_enabled()): # Do something if the functionality is enabled.
And that's it for this sub-addon!