Debug Menu
A scene that holds other scenes which are tools to help debug the game.
Goals
The Goal of the Debug Menu is to be the main HUD for other scenes that allow us to quickly cheat, change aspects of the game, or whatever else helps testing/debugging.
How it works
The scene itself is located at res://src/DebugMenu.tscn
and since it is just a "Container" of other scenes that are the debug tools themselves, this scene and its logic is pretty simple.
It listens to input and reacts to the action "ui_debug_levels"
. Whenever this action is released it will toggle the debug menu to either _open()
or _close()
. These functions already take care of pausing the game and handling keyboard/controller focus.
It is dynamically instanced by Game.tscn
when it recognizes that the current build is a "debug" build.
Accessing other nodes from the DebugMenu
Many times some tool inside the DebugMenu will have to access specific nodes, like LinearWorld
, Player
, or DayNightCycle
.
An "easy" solution for that is using find_node
on the root.
var _player = get_tree().root.find_node("Player", true, false) as Player
It is usually frowned upon and discouraged to use find_node
as it is and expensive function and might make some weird couplings, but since this is just a debug menu and not actual gameplay logic, and if it's not something that will run on a loop or on process
, then it can be used.
It might be good to try to cache the reference to avoid having to find the node every time a button is pressed. But, since the DebugMenu lives on Game and is persistent through scene changes, a "player" or "world" node that you've cached might not be valid anymore. This is an how PlayerDebugTool
deals with it:
This way I run _is_player_valid()
at the start of any functions that needs a reference to the player. If it has no reference it will grab one and check that it is valid. If it already has one and it's still valid, it will just return true. And if it can't find a valid reference it will return false and let me exit the function that needs the player.
Setting up the Debug Menu export vars
DebugMenu
has one export vars:
_path_first_focus
is an "internal" export var, as in, it's not meant to be edited from outside of the scene. It's just to choose which of the debug tools will receive the keyboard/controller focus whenDebugMenu
is first opened.
Making DebugMenu "sections" keyboard/controller friendly
Godot is usually pretty good at understanding focus between control nodes and navigating through them with a controller/keyboard. What happens sometimes is that when you are navigating focus goes to a "container" control that shows no feedback.
To make any scene keyboard/controller friendly inside the current scenes from the DebugMenu, I had to connect the focus_entered
signal of the root control node of the scene to itself, and then make a desired first button grab the focus:
With just that in each of the "child" scenes from the DebugMenu it's enough for Godot itself to handle navigation between the buttons of each section and not "lose" focus when navigating between sections.
With what script it communicates
With LinearWorld
, DayNightCycle
, Player
and possibly whatever tool is inside it and what they require.