Debugging Projects in Godot
When analyzing code, the errors might not be obvious just by looking at the code. To help you analyze and debug code, use the provided debugger integrated in Godot. By Ricardo Santos.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Debugging Projects in Godot
25 mins
- Getting Started
- Overview of the Debug Tools
- Debugger Panel
- Using Breakpoints
- Breakpoints
- Adding Breakpoints to the Project
- Using the Debugger Panel
- Stack Trace Tab
- Errors Tab
- Using the Profiler
- Profiler Information
- Using the Profiler to Optimize the Game
- Visual Profiler Tab
- Custom Monitors
- Creating Custom Performance Monitors
- Using Custom Performance Monitors
- Where to Go From Here?
Using the Profiler
The profiler provides an overview of the time spent in each part of the game. Every frame, Godot performs the calculations for every entity instantiated. This means the engine must divide the time available between frames for all the elements in the scene.
The profiler helps to visualize how long each function takes to execute in each frame. The game ran slow because some function must be taking too long to execute. Using the profiler, you can see which function takes how long to execute.
Profiler Information
Click the Run project button and wait for the initial screen to appear. Before beginning the game, go back to the Godot screen and, on the Debugger panel, select the Profiler tab and click the Start button.
You’ll notice that the window begins to update with the data from the game. Begin the game, shoot at some enemy ships and notice how the graph changes to something like this:
That’s a huge leap! On the left side, you can see that the time used by the Process Time item is almost 2 seconds, which means that the game runs at 0.5 fps.
Notice that the list on the left side has many more entries than the ones showing now.
Scroll to the bottom of the list until you find Script Functions. The first item seems to be the one taking more time to process.
By hovering the mouse pointer over the text _process, you can see a bit more information about the process:
In this case, the impact is severe enough that you can see beyond the shadow of a doubt that the issue comes from this function alone. However, in some cases it might be more difficult to discover these issues just by looking at the time spent in each function.
In those cases, it might be useful to see how much each part of the code consumes as a percentage. To change to this view, click the Measure dropdown box and change from Frame Time (ms) to Frame%.
Observing the new visualization, you notice that the _process() function is taking more than 99% of the frame processing time. At least this confirms the suspicion that this is the pain point in the project.
This tool has shown that, indeed, the main performance issue in the project now was inserted through the _process() function in main_game.gd script. Hence, the task now is to remove these lines.
Using the Profiler to Optimize the Game
Open the main_game.gd script and remove the _process() function.
Click the Run project function again and start the profiler again. Shoot some enemies and close the game. The profiler should show something like this:
That’s a much better process time. It dropped from about 2 seconds to roughly 2 milliseconds — an improvement of 1000 times in processing speed!
There’s the possibility of another pain point appearing and needing to be dealt with after removing that initial one. If that was the case, you would only need to repeat the process for the new issue. However, the project looks good the way it is.
Visual Profiler Tab
Another profiling tool Godot offers measures how long the rendering tasks take, disregarding other engine aspects such as scripting, physics and networking. This tool is useful to review the project and how the rendering pipeline is working.
In the case of Aerixa, there is no pain point here, but there is no harm in having a look to make sure, right?
The process is the same as before: Launch the project, start the Visual Profiler by clicking in the Start button, play for a little while and then close the game. You should see a graph that resembles this:
Notice how Godot tries to keep rendering time below 16.67 milliseconds, the necessary time for providing a 60 fps game. You can see that the graph is divided in two: the left side shows the CPU processing time, and the right side shows the GPU processing time.
Custom Monitors
As comprehensive and useful as Godot’s debug tools are, you might want to know something that they cannot tell you by default. Suppose you would like to know how many bullets have been fired or how many enemy ships the players have destroyed. No out-of-the-box tools for this.
Godot allows you to create custom monitors. Through custom monitors, you can track values of interest, in addition to the monitors Godot already provides.
As you can see, Godot already has information regarding how some elements have progressed during gameplay. But you could add your own information.
Creating Custom Performance Monitors
To create a performance monitor, you’ll use Performance.add_custom_monitor(String name, function callback), available natively in Godot.
The function takes two arguments:
- name: The monitor’s name in the format Category/Name. The category is under which category the monitor should be placed, such as Time/FPS or Memory/Static. If no category is defined, the monitor will be placed automatically under the generic Custom category.
- callback: The function that returns an integer greater than or equal to zero. This is the value Godot will use to plot the graph.
Initially, you need a counting function for the enemies. Go to the bottom of the main_game.gd script and add the following function:
func count_enemy_ships():
return get_node("/root/MainGame/EnemyManager").get_child_count()
When an enemy gets spawned in the scene, it is instantiated as a child of the EnemyManager node. This function counts how many children this node has and returns this value.
To finish creating your monitor, you must register this function in Godot when the scene is created. Go to the _ready() function and add the following line just below the function signature:
func _ready() -> void:
Performance.add_custom_monitor("Game/EnemyShips", count_enemy_ships)
# [...] The rest of the function that is already in the project.
This function creates a group called Game and adds a monitor called Enemy Ships under it. This will only be created when the game starts running, so it won’t be in the editor as soon as you add it to the code.
And you’re set!