Install Asset
Install via Godot
To maintain one source of truth, Godot Asset Library is just a mirror of the old asset library so you can download directly on Godot via the integrated asset library browser
Quick Information
Universal, scalable, production-ready debugging system for Godot 4.x.Drop the addon, enable the plugin, and get 50+ built-in monitors (FPS, memory, GPU, draw calls, physics, scene tree, audio, network, system info, ...) with one line of code: DebugAPI.enable_monitor_preset("essential")Or build your own panels with declarative widgets — bind a value to a TextWidget / ProgressWidget / GraphWidget / ConditionalWidget / TimerWidget / VectorWidget and it auto-refreshes. Smart-diff updates and per-widget rate limiting keep the panel under 1 ms/frame even with 50+ widgets active.FEATURES• 50+ built-in monitors organised in 12 categories (performance, memory, objects, rendering, physics, audio, display, system, time, input, scene, network)• 8 named presets (minimal, essential, performance, memory, rendering, system, display, full)• 7 built-in themes (Default, Dark, Light, Neon, Retro, Minimal, Solarized) + full custom• 4 install modes: editor plugin (recommended), manual autoload, drop-in DebugBootstrap node, pure instance via preload• Inspector-driven configuration via a DebugSettings resource• 8 anchor presets (corners, edges, centre, free) with edge_margin and viewport-aware repositioning• Optional title bar, collapsible sections, scrollable panels, custom font support, click-through• Hotkeys via InputMap actions or raw keycodes; global toggle and export shortcuts• TXT / JSON / CSV export with auto-detection by file extension; auto-export on interval• Settings persistence: snapshot_settings() + save/load to .tres• Zero-code config: drop res://debug_settings.tres and the API auto-applies it on _ready• Headless-safe; runs on Forward+, Mobile and Compatibility renderers• Multi-language documentation (English, Español, Français, Deutsch, Português) included• Godot 4.0+ (tested on 4.4.1)DOCUMENTATIONFull README with step-by-step tutorial, monitor catalogue, widget reference, theme gallery, configuration reference, hotkeys, export guide, performance notes, troubleshooting and complete API reference at the repository.LICENSEMIT — free for any use, attribution preserved via the copyright notice.
Universal, scalable, production-ready debugging for Godot 4.x.
Drop in. Pick a preset. Watch FPS, memory, GPU, physics, render counters and 50+ other metrics — without writing a single Label.
🇬🇧 English · 🇪🇸 Español · 🇫🇷 Français · 🇩🇪 Deutsch · 🇧🇷 Português
🇬🇧 English
📋 Table of Contents
- Overview
- Features
- Architecture
- Installation — four modes
- Quick Start (60 seconds)
- Step-by-Step Tutorial
- Built-in Monitors Catalog
- Custom Panels & Widgets
- Widget Reference
- Themes
- Configuration Reference (DebugSettings)
- Hotkeys & Input Actions
- Export & Persistence
- Performance Notes
- Troubleshooting
- API Reference
- Migration from v0.x
🎮 Overview
Debug API turns the boilerplate of "show FPS, show this variable, show that timer" into a one-line declaration. Drop the addon in, enable the plugin, and you get:
- ~50 built-in monitors (FPS, frame time, memory, GPU, draw calls, physics, scene tree, audio, network, system info, ...) that you can enable individually, by category, or with named presets.
- A declarative widget API for custom variables — bind any value to a
TextWidget/ProgressWidget/GraphWidget/ etc. and it auto-refreshes. - Inspector-driven configuration through a
DebugSettingsresource — every option is also exposed via code. - Themes, anchors, collapsible sections, custom fonts, optional title bar, click-through, hotkeys via
InputMapactions, JSON/CSV/TXT export, auto-export on interval, snapshot persistence, conditional debug-only initialization. - Smart-diff updates and per-widget refresh throttling so a full preset stays under 1 ms/frame even with 50+ widgets.
Version:
v1.0· Engine: Godot 4.0+ · Language: GDScript · Type: Plugin (autoload + Resource + Bootstrap node)
The problem. Every project re-implements Label + _process to display FPS, then variables, then timers. Lots of CanvasLayers, formatting code, hotkey handling.
The solution. A central API that owns the panel rendering and lets you declare what to show, not how to show it.
✨ Features
| Category | What you get |
|---|---|
| Built-in monitors | FPS (current/avg/min/max/graph), frame time, process time, physics process, navigation process, static memory + peak, message queue, video memory, texture memory, buffer memory, total objects, node count, resource count, orphan nodes, render objects/primitives/draw calls, GPU name/vendor/type, rendering method, physics 2D/3D bodies/pairs/islands, audio latency, window/screen size/position/DPI/refresh rate, aspect ratio, fullscreen/window mode/vsync, OS, CPU, cores, architecture, engine version, locale, debug build flag, time scale, physics tps, uptime, system time, mouse position, joypads, current scene, scene-tree node count, multiplayer ID, peers. |
| Widgets | Text, Progress bar, Graph (history), Conditional (boolean), Coloured (threshold-driven), Timer, Vector. |
| Presets | minimal, essential, performance, memory, rendering, system, display, full. |
| Themes | Default, Dark, Light, Neon, Retro, Minimal, Solarized + full custom. |
| Layout | 8 anchor presets (corners, top/bottom centre, centre, free), edge margins, padding, corner radius, border, custom font, optional title bar, scrollable when content exceeds max_height. |
| Behaviour | Collapsible sections, click-through, per-panel toggle (key + InputMap action), global toggle, export hotkey, auto-export every N s, only-in-debug-build flag, paused mode. |
| Export | TXT (default), JSON, CSV — auto-detected by extension. |
| Persistence | save_settings(...) / load_settings(...) / snapshot_settings() — round-trip your runtime customizations to a .tres. |
| Auto-config | Drop res://debug_settings.tres and it's applied on _ready — zero code. |
| Performance | Smart-diff (skip Label assignment when value unchanged), per-widget update_interval, hidden widgets skipped, paused-state for instant on/off, get_perf_stats(). |
| Compatibility | Godot 4.0+, headless-safe, Forward+ / Mobile / Compatibility renderers, multi-platform. |
🏗️ Architecture
DebugAPI (autoload OR DebugBootstrap-managed)
│
├── _process() ── DebugMonitors.tick() (1 float/frame for FPS history)
│
├── Auto panel ── "__auto__" (built-in monitors live here)
│ └── sections by category (Performance, Memory, Display, ...)
│
└── Custom panels (your code)
└── DebugPanel ─ sections ─ widgets
│
├── TextWidget
├── ProgressWidget
├── GraphWidget
├── ConditionalWidget
├── ColoredWidget
├── TimerWidget
└── VectorWidget
res://addons/debug_api/
├── plugin.cfg # plugin manifest
├── plugin.gd # EditorPlugin (auto-registers the "DebugAPI" autoload)
├── DebugAPI.gd # entry point (NO class_name — autoload owns the name)
├── DebugPanel.gd # panel hosting widgets
├── DebugWidgets.gd # widget classes (Text, Progress, Graph, ...)
├── DebugMonitors.gd # registry of built-in monitors
├── DebugThemes.gd # named colour presets
├── DebugSettings.gd # Resource — the "config from inspector" path
├── DebugBootstrap.gd # drop-in Node for projects that don't want autoloads
└── examples/
├── DebugExample.gd # custom panel + auto-monitors
├── AutoMonitorsExample.gd # minimal auto-monitor demo
├── BootstrapExample.gd # no-autoload setup
└── AdvancedConfigExample.gd # themes, hotkeys, JSON export, scrollable panel
📦 Installation — four modes
Pick one. Each is fully production-grade.
① Plugin — recommended
- Copy
addons/debug_api/into your project'sres://addons/directory. - Project Settings → Plugins → Debug API → enable.
- Use anywhere:
func _ready(): DebugAPI.enable_monitor_preset("essential")
The plugin auto-registers an autoload named DebugAPI. The script DebugAPI.gd deliberately has no class_name — its name is reserved for the autoload (Godot 4.4+ rejects class_name + autoload sharing a name).
② Manual autoload
If you don't want plugin enabled (e.g. CI, headless), register the autoload yourself:
- Project Settings → Autoload → Path:
res://addons/debug_api/DebugAPI.gd, Name:DebugAPI→ Add.
Same code as Method ①.
③ Bootstrap node — no autoload
Drag a DebugBootstrap node into your main scene. From the inspector:
- either pick a
quick_preset(none / minimal / essential / performance / memory / rendering / system / display / full), - or assign a
DebugSettings.tresresource for full control.
Access from code via bootstrap.api. This mode is ideal for libraries, plugins of plugins, or projects that strictly avoid autoloads.
④ Pure instance / library mode
For tests, embedded contexts, or maximum decoupling:
const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd")
var api := DebugAPIScript.new()
add_child(api)
api.enable_monitor("fps")
DebugAPI.gd has no class_name, so you reach it through preload(...). Everything else (DebugPanel, DebugSettings, DebugMonitors, DebugThemes, DebugWidgets, DebugBootstrap) does have class_name — you can refer to them directly.
🚀 Quick Start (60 seconds)
After installing the plugin (Method ①):
extends Node
func _ready():
DebugAPI.enable_monitor_preset("essential")
Run the project. The panel shows FPS, frame time, static memory, node count and window size. Press F1 to toggle visibility.
Want everything?
DebugAPI.enable_all_monitors()
Want only FPS?
DebugAPI.enable_monitor("fps")
Want a different look?
DebugAPI.apply_theme("neon")
Done. Read on for the full tour.
📖 Step-by-Step Tutorial
Step 1 — Install
Copy addons/debug_api/ into your project. Enable the plugin in Project Settings → Plugins.
You should see no errors in the Output panel and a new autoload "DebugAPI" listed in Project Settings → Autoload.
Step 2 — Show your first metric
Anywhere in your code:
extends Node
func _ready():
DebugAPI.enable_monitor("fps")
Run. The FPS counter appears top-left. Press F1 to hide / show.
Step 3 — Pick a preset
Replace the call with:
DebugAPI.enable_monitor_preset("performance")
Now you see FPS, average FPS, min FPS, max FPS, frame time, process time and physics process. Other presets:
"minimal" → FPS only
"essential" → FPS, frame time, memory, nodes, window size
"performance" → FPS family, frame time, process times
"memory" → static, peak, video, texture, buffer, orphans
"rendering" → objects, primitives, draw calls, GPU info
"system" → OS, CPU, cores, GPU, engine version
"display" → window/screen size, DPI, refresh, fullscreen, vsync
"full" → everything (~50 widgets)
You can also enable a category in one shot:
DebugAPI.enable_monitor_category("memory")
Step 4 — Configure from the inspector
Programmatic config is great, but for "set and forget" you can drive everything from a DebugSettings resource.
- In the FileSystem dock, right-click → New Resource… → search DebugSettings → Create.
- Save it as
res://debug_settings.tres. - Open it. The inspector lists groups: Quick Setup, By Category, Specific Monitors, Position, Panel Behavior, Hotkeys, Panel Layout, Title Bar, Style, Export.
- Tick the categories you want. Adjust the colours, hotkey, anchor — whatever you fancy.
- Run the project.
DebugAPIauto-loadsres://debug_settings.treson_readyand applies it. No code needed.
If you prefer a different filename or want to apply on demand:
var settings: DebugSettings = load("res://my_settings.tres")
DebugAPI.apply_settings(settings)
The auto-load also looks at res://addons/debug_api/debug_settings.tres and user://debug_settings.tres.
Step 5 — Custom widgets
The built-in monitors cover engine state. For your state, build a panel:
extends CharacterBody2D
var health: float = 100.0
var coyote_timer: Timer
var debug_panel: DebugPanel
func _ready():
coyote_timer = Timer.new()
coyote_timer.wait_time = 0.12
coyote_timer.one_shot = true
add_child(coyote_timer)
debug_panel = DebugAPI.create_panel("Player", self, {
"anchor": DebugPanel.ANCHOR_TOP_RIGHT,
"edge_margin": Vector2(8, 8),
})
debug_panel.add_text_widget("STATE", "Position", func(): return global_position, "(%.0f, %.0f)")
debug_panel.add_progress_widget("STATE", "Health", func(): return health, 0.0, 100.0)
debug_panel.add_timer_widget("TIMERS", "Coyote", coyote_timer)
debug_panel.add_conditional_widget("STATE", "Grounded",
func(): return is_on_floor(), func(v): return v, "🟢 YES", "🔴 NO")
The panel updates itself every frame. The Player panel has its own toggle key (default F1, configurable via the config dictionary).
Step 6 — Apply a theme
DebugAPI.apply_theme("dark")
Available: default, dark, light, neon, retro, minimal, solarized. The theme replaces the auto-panel colours; your monitors stay enabled and re-skin instantly.
From the inspector, set theme_preset on DebugSettings to anything other than Custom and the individual colour pickers below it are ignored (the theme wins).
Step 7 — Export hotkey
DebugAPI.export_hotkey = KEY_F3
DebugAPI.export_path = "user://debug.json"
DebugAPI.export_format = DebugAPI.EXPORT_JSON
Press F3 in-game and the current state of every panel is written to user://debug.json. Format auto-detection works too:
DebugAPI.export_debug_data("user://snapshot.csv") # → CSV
DebugAPI.export_debug_data("user://snapshot.json") # → JSON
DebugAPI.export_debug_data("user://snapshot.txt") # → TXT
For periodic snapshots:
DebugAPI.auto_export_path = "user://logs/auto.json"
DebugAPI.auto_export_format = DebugAPI.EXPORT_JSON
DebugAPI.auto_export_interval = 30.0 # every 30 s
Step 8 — Persist your customizations
You spent ten minutes tweaking colours, hotkey, layout. Save the result:
var snap := DebugAPI.snapshot_settings()
DebugAPI.save_settings(snap, "user://my_debug.tres")
Next launch:
var loaded := DebugAPI.load_settings("user://my_debug.tres")
if loaded:
DebugAPI.apply_settings(loaded)
Or ship the .tres with your project at res://debug_settings.tres and the auto-load handles it.
That's the whole tour. The remaining sections are reference material.
📊 Built-in Monitors Catalog
Every monitor has a stable string id. Use it with enable_monitor(id) or include it in DebugSettings.monitor_ids.
Performance — category: "performance"
| id | label | widget | refresh |
|---|---|---|---|
fps |
FPS | colored | per frame |
fps_avg |
Avg FPS | colored | per frame |
fps_min |
Min FPS | colored | per frame |
fps_max |
Max FPS | text | per frame |
frame_time |
Frame Time | colored (ms) | per frame |
process_time |
Process Time | text | per frame |
physics_process_time |
Physics Process | text | per frame |
navigation_process_time |
Navigation Process | text | per frame |
fps_graph |
FPS Graph | graph | per frame |
Memory — category: "memory"
| id | label | widget | refresh |
|---|---|---|---|
memory_static |
Static Memory | text | per frame |
memory_static_max |
Peak Memory | text | per frame |
message_queue_max |
Message Queue Peak | text | per frame |
video_memory |
Video Memory | text | per frame |
texture_memory |
Texture Memory | text | per frame |
buffer_memory |
Buffer Memory | text | per frame |
Objects — category: "objects"
| id | label | widget | refresh |
|---|---|---|---|
object_count |
Total Objects | text | per frame |
node_count |
Nodes | text | per frame |
resource_count |
Resources | text | per frame |
orphan_nodes |
Orphan Nodes | colored | per frame |
Rendering — category: "rendering"
| id | label | widget | refresh |
|---|---|---|---|
total_objects |
Objects in Frame | text | per frame |
total_primitives |
Primitives | text | per frame |
total_draw_calls |
Draw Calls | text | per frame |
rendering_method |
Rendering Method | text | every 60 s |
gpu_name |
GPU | text | every 60 s |
gpu_vendor |
GPU Vendor | text | every 60 s |
gpu_type |
GPU Type | text | every 60 s |
Physics — category: "physics"
active_bodies_2d, collision_pairs_2d, physics_islands_2d, active_bodies_3d, collision_pairs_3d, physics_islands_3d. All int, refresh per frame.
Audio — category: "audio"
audio_latency — float ms, refresh every 1 s.
Display — category: "display"
window_size, window_position, screen_size, screen_dpi, screen_refresh_rate, aspect_ratio, fullscreen (conditional), window_mode, vsync_mode. Refresh 0.5 – 5 s depending on metric.
System — category: "system"
os_name, os_version, cpu_model, cpu_cores, architecture, engine_version, locale, debug_build. Mostly refresh every 60 s (essentially immutable values).
Time — category: "time"
time_scale (per frame), physics_ticks_per_second (5 s), uptime (1 s), system_time (0.5 s).
Input — category: "input"
mouse_position (vector, per frame), joypad_count (0.5 s).
Scene — category: "scene"
current_scene (1 s), scene_tree_node_count (0.2 s).
Network — category: "network"
multiplayer_id (1 s), multiplayer_peers (0.5 s).
Custom monitors
Register your own at runtime:
DebugAPI.register_custom_monitor({
"id": "frames_drawn",
"label": "Frames Drawn",
"category": "performance",
"widget_type": "text",
"format": "%d",
"getter": func(): return Engine.get_frames_drawn(),
})
DebugAPI.enable_monitor("frames_drawn")
Optional keys: update_interval (sec), color_ranges (for "colored" widgets), condition / true_text / false_text (for "conditional"), history_size (for "graph"), min / max (for "progress").
🎨 Custom Panels & Widgets
DebugAPI.create_panel(name, parent, config) builds a fresh panel for your code:
var panel := DebugAPI.create_panel("AI", get_tree().current_scene, {
"anchor": DebugPanel.ANCHOR_BOTTOM_RIGHT,
"edge_margin": Vector2(8, 8),
"min_width": 240,
"max_height": 400, # scrollable beyond this
"panel_padding": 8,
"corner_radius": 6,
"show_title": true,
"title_text": "AI Brain",
"collapsible_sections": true,
"toggle_key": KEY_F4,
"background_color": Color(0, 0.05, 0.1, 0.9),
})
The panel parents itself to a CanvasLayer placed under the supplied parent. Toggle keys are per-panel, so multiple panels can coexist with different shortcuts.
Add widgets via the dedicated methods (see the Widget Reference) or via add_monitor(monitor_dict) for a metadata-driven flow that mirrors the built-in monitors.
Multiple panels:
DebugAPI.create_panel("Player", player_node, {"anchor": DebugPanel.ANCHOR_TOP_LEFT})
DebugAPI.create_panel("Enemy", enemy_node, {"anchor": DebugPanel.ANCHOR_TOP_RIGHT})
DebugAPI.create_panel("World", world_node, {"anchor": DebugPanel.ANCHOR_BOTTOM_LEFT})
Each gets its own toggle. Use DebugAPI.toggle_global_visibility() (or assign global_toggle_key) to hide/show all at once.
🔧 Widget Reference
All widget creators return the widget instance so you can store a reference and tweak it later.
TextWidget
panel.add_text_widget(section: String, label: String, getter: Callable, format := "%s")
Plain "key: value". Smart-diff skips re-rendering when the value is unchanged.
panel.add_text_widget("PLAYER", "Health", func(): return health, "%d / 100")
ProgressWidget
panel.add_progress_widget(section, label, getter, min_val := 0.0, max_val := 1.0)
Visual bar with built-in percentage label.
panel.add_progress_widget("PLAYER", "Mana", func(): return mana, 0.0, 100.0)
GraphWidget
panel.add_graph_widget(section, label, getter, history_size := 30)
Sliding-window line graph. Rebuilds every update.
panel.add_graph_widget("PERF", "FPS", func(): return Engine.get_frames_per_second(), 60)
ConditionalWidget
panel.add_conditional_widget(section, label, getter, condition,
true_text := "✓", false_text := "✗")
Boolean state. Different colour for each branch.
panel.add_conditional_widget("STATE", "Grounded",
func(): return is_on_floor(),
func(v): return v,
"🟢 ON", "🔴 OFF")
ColoredWidget
panel.add_colored_widget(section, label, getter, ranges := [], format := "%s")
Threshold-driven colour. Each range is {"condition": Callable(value) -> bool, "color": Color}. The first matching range wins.
panel.add_colored_widget("PERF", "FPS", func(): return Engine.get_frames_per_second(),
[
{"condition": func(v): return v >= 55, "color": Color.GREEN},
{"condition": func(v): return v >= 30, "color": Color.YELLOW},
{"condition": func(v): return true, "color": Color.RED},
],
"%d FPS")
TimerWidget
panel.add_timer_widget(section, label, timer: Timer, show_max := true)
Visualises a Timer node — time_left / wait_time.
panel.add_timer_widget("TIMERS", "Coyote", coyote_timer)
VectorWidget
panel.add_vector_widget(section, label, getter, format := "(%.1f, %.1f)")
Auto-formats Vector2 and Vector3.
panel.add_vector_widget("MOTION", "Velocity", func(): return velocity)
Per-widget update_interval
After creation:
var w := panel.add_text_widget("INFO", "GPU", func(): return RenderingServer.get_video_adapter_name())
w.update_interval = 60.0 # refresh once a minute
For built-in monitors at the API level:
DebugAPI.set_monitor_update_interval("orphan_nodes", 0.5)
Removing widgets
panel.remove_widget(my_widget)
panel.clear() # all widgets in this panel
DebugAPI.disable_monitor("fps")
DebugAPI.disable_all_monitors()
🎨 Themes
| Theme | Use case |
|---|---|
| Default | Translucent black, soft blue labels. Production-friendly default. |
| Dark | Solid near-black background, high-contrast text. Good for streaming. |
| Light | Off-white background, navy text. Daytime / light-themed UIs. |
| Neon | Cyber-style: dark background, electric green/magenta accents. |
| Retro | Terminal feel: amber-on-dark-green, bright green section headers. |
| Minimal | Transparent background, white text. Overlay on top of existing UI without visual weight. |
| Solarized | Solarized-Dark palette. Comfortable for long sessions. |
Apply by name from code:
DebugAPI.apply_theme("solarized")
Or set theme_preset on DebugSettings (any value other than Custom overrides the individual colour exports below it).
⚙️ Configuration Reference (DebugSettings)
Every property is @exported. Inspector groups in bold.
| Property | Type | Default | Purpose |
|---|---|---|---|
| Quick setup | |||
preset |
int (enum) | none |
Apply a built-in monitor preset. |
theme_preset |
int (enum) | Default |
Built-in theme. Custom uses the colour exports below. |
only_in_debug_build |
bool | false |
Skip initialization in release builds. |
| By Category | |||
enable_performance … enable_network |
bool | false |
Toggle every monitor in that category. |
| Specific Monitors | |||
monitor_ids |
Array[String] | [] |
Additional ids to enable on top of preset/categories. |
| Position | |||
anchor |
int (enum) | Top Left |
Where the panel sits. Free uses raw free_position. |
edge_margin |
Vector2 | (8, 8) |
Distance from anchored edge. |
free_position |
Vector2 | (8, 8) |
Used when anchor = Free. |
| Panel Behavior | |||
start_visible |
bool | true |
Initial visibility. |
update_interval |
float | 0.0 |
Panel-wide refresh throttle (s). 0 = every frame. |
click_through |
bool | true |
If true, panel doesn't block clicks. |
collapsible_sections |
bool | false |
Section titles become buttons that fold. |
| Hotkeys | |||
toggle_key |
int (Key) | KEY_F1 |
Per-panel toggle keycode. KEY_NONE disables. |
toggle_action |
String | "" |
InputMap action name (priority over keycode). |
global_toggle_key |
int | KEY_NONE |
Hides every panel. |
global_toggle_action |
String | "" |
InputMap variant. |
export_hotkey |
int | KEY_NONE |
Triggers export_debug_data. |
export_action |
String | "" |
InputMap variant. |
| Panel Layout | |||
min_width |
int | 250 |
Minimum panel width. |
max_height |
float | 0.0 |
When > 0, panel becomes scrollable. |
canvas_layer |
int | 100 |
CanvasLayer index. |
spacing |
int | 4 |
Pixel spacing between rows. |
panel_padding |
int | 6 |
Inner padding. |
border_width |
int | 1 |
0 = no border. |
corner_radius |
int | 0 |
Rounded corners. |
| Title Bar | |||
show_title |
bool | false |
Show a centred title above sections. |
title_text |
String | "" |
Falls back to panel name when empty. |
| Style (used only when theme_preset = Custom) | |||
background_color |
Color | (0,0,0,0.7) |
Panel background. |
border_color |
Color | (0.5,0.5,0.5,0.8) |
Border colour. |
font_color |
Color | (0.76,0.86,1,1) |
Left-side label colour. |
section_color |
Color | (1,1,0.5,1) |
Section title colour. |
title_color |
Color | (1,1,1,1) |
Title bar colour. |
value_color |
Color | (1,1,1,1) |
Right-side value colour. |
shadow_color |
Color | (0,0,0,0.85) |
Text shadow colour (alpha 0 = no shadow). |
shadow_offset |
Vector2 | (1,1) |
Text shadow offset. |
font_size |
int | 13 |
Text size. |
custom_font |
Font | null |
FontFile / SystemFont resource. |
| Export | |||
export_path |
String | user://debug_export.txt |
Hotkey export destination. |
export_format |
int (enum) | TXT |
TXT / JSON / CSV. |
auto_export_interval |
float | 0.0 |
0 = disabled. |
auto_export_path |
String | "" |
Auto-export destination. |
auto_export_format |
int (enum) | TXT |
TXT / JSON / CSV. |
Programmatic equivalent
Every export is also a public field on the corresponding API or a key in the panel config dictionary. DebugSettings.to_panel_config() does the conversion under the hood.
⌨️ Hotkeys & Input Actions
Two layers:
- Per-panel — each
DebugPanelowns atoggle_key(defaultKEY_F1) and an optionaltoggle_action. When set, the action takes priority over the keycode. - Global on
DebugAPI—global_toggle_key/global_toggle_actionhide every panel;export_hotkey/export_actionwrite a snapshot toexport_path.
Use InputMap actions when your project already manages remappable input. Example:
- Project Settings → Input Map → New action
debug_toggle→ bind to F1. - In code:
var settings := DebugSettings.new() settings.toggle_action = "debug_toggle" DebugAPI.apply_settings(settings)
Set toggle_key = KEY_NONE and toggle_action = "" to disable a panel's hotkey entirely.
Avoid double-handling: don't set
global_toggle_keyto the same key as a panel'stoggle_key— the event fires both handlers and the visible state ping-pongs.
💾 Export & Persistence
Export current state
DebugAPI.export_debug_data() # default path/format
DebugAPI.export_debug_data("user://snap.json") # extension auto-detect
DebugAPI.export_debug_data("user://snap.csv", DebugAPI.EXPORT_CSV)
The data_exported(filepath, format) signal fires on success.
Auto-export
DebugAPI.auto_export_path = "user://logs/auto.json"
DebugAPI.auto_export_format = DebugAPI.EXPORT_JSON
DebugAPI.auto_export_interval = 30.0
Set auto_export_interval = 0.0 to stop.
Persist your customizations as a Resource
# Save current API state
var s := DebugAPI.snapshot_settings()
DebugAPI.save_settings(s, "user://my_debug.tres")
# Restore later
var loaded := DebugAPI.load_settings("user://my_debug.tres")
if loaded:
DebugAPI.apply_settings(loaded)
Auto-load a settings .tres on startup
Drop a DebugSettings resource at any of the following paths and _ready applies it automatically:
res://debug_settings.tresres://addons/debug_api/debug_settings.tresuser://debug_settings.tres
If you've already called apply_settings(...) explicitly, the auto-load skips itself (so DebugBootstrap can win).
⚡ Performance Notes
- Smart-diff — every text-style widget compares the new value against the previous one and skips the
Label.textwrite when unchanged. The dominant cost in tight loops disappears. - Per-widget
update_interval— built-in monitors are pre-tagged. Static stuff likegpu_nameupdates once a minute; window/screen metadata at 0.5–1 Hz; per-frame metrics every frame. Configure further withDebugAPI.set_monitor_update_interval(id, seconds)orwidget.update_interval = …. - Hidden widgets are skipped —
update_display()checksis_visible_in_tree()and bypasses widgets in collapsed sections or hidden panels. - Pause —
DebugAPI.paused = truehalts the FPS sampler, every panel's_processand the auto-export tick.paused = falseresumes. Cheap on/off switch. - Conditional initialization —
DebugSettings.only_in_debug_build = truemakesapply_settingsa no-op in non-debug builds. Zero overhead in production. - Introspection —
DebugAPI.get_perf_stats()returns{panels, total_widgets, enabled_monitors, fps_history_size, paused, only_in_debug}.
A "full" preset (~50 widgets) at 60 Hz with smart-diff and per-widget throttling typically costs less than 0.5 ms/frame on desktop.
🩺 Troubleshooting
"Nombre inválido. No debe colisionar con un nombre de clase de script global existente."
You have a class_name DebugAPI somewhere AND you're trying to register an autoload also named DebugAPI. Godot 4.4+ rejects this. Solution: ensure DebugAPI.gd does not declare class_name. The plugin / autoload owns the name.
"Cannot call non-static function on the class 'DebugAPI' directly. Make an instance instead."
Same root cause as above — DebugAPI resolves to the class type instead of the autoload instance. Remove class_name DebugAPI, re-enable the plugin.
Errors mention paths like res://addons/debug_api/addons/debug_api/...
You have a duplicated/nested addon folder OR Godot's class registry cached old paths. Fix:
- Close Godot.
- Verify
res://addons/debug_api/does not contain anotheraddons/subfolder. If it does, delete the nested copy. - Delete the project's
.godot/folder (Godot regenerates it). - Reopen the project; let it finish scanning.
DebugSettings doesn't appear in New Resource → Debug…
Almost always the same stale-cache problem above. Delete .godot/ and reopen. If it still doesn't appear, open DebugSettings.gd and confirm it has @tool, class_name DebugSettings, extends Resource.
Auto-load of debug_settings.tres does nothing
Three checks:
- The file exists at one of the paths and is actually a
DebugSettingsresource (not a generic.tres). - You haven't called
apply_settings(...)somewhere earlier — the auto-load is intentionally skipped after an explicit apply. only_in_debug_build = trueand you're running an export build.
To force a re-scan: DebugAPI.reload_auto_settings().
Display monitors all show 0
Headless build — DisplayServer returns zeros. Disable the display category in your settings if it bothers you.
Panel blocks game input
Set click_through = true (default in v1.0). Buttons inside the panel still receive their own clicks because mouse_filter is per-Control.
📚 API Reference
DebugAPI (autoload / instance)
Monitors
enable_monitor(id: String) -> bool
enable_monitors(ids: Array) -> void
enable_monitor_category(category: String) -> void
enable_monitor_preset(preset_name: String) -> void
enable_all_monitors() -> void
disable_monitor(id: String) -> void
disable_monitors(ids: Array) -> void
disable_monitor_category(category: String) -> void
disable_all_monitors() -> void
is_monitor_enabled(id: String) -> bool
list_enabled_monitors() -> Array
list_available_monitors() -> Array
list_categories() -> Array
list_presets() -> Array
get_monitor_info(id: String) -> Dictionary
register_custom_monitor(monitor: Dictionary) -> bool
set_monitor_update_interval(id: String, seconds: float) -> bool
Panels
create_panel(panel_name: String, parent_node: Node, config := {}) -> DebugPanel
get_panel(panel_name: String) -> DebugPanel
has_panel(panel_name: String) -> bool
remove_panel(panel_name: String) -> void
list_panels() -> Array
update_all() -> void
get_auto_panel() -> DebugPanel
configure_auto_panel(config: Dictionary) -> void
set_auto_panel_parent(parent: Node) -> void
Settings
apply_settings(settings: DebugSettings) -> void
apply_theme(theme_name: String) -> void
snapshot_settings() -> DebugSettings
reload_auto_settings() -> bool
static save_settings(settings: DebugSettings, path: String) -> int # Error
static load_settings(path: String) -> DebugSettings
Visibility / hotkeys
toggle_global_visibility() -> void
global_visible: bool
paused: bool
global_toggle_key: int
global_toggle_action: String
export_hotkey: int
export_action: String
export_path: String
export_format: int # EXPORT_TXT / EXPORT_JSON / EXPORT_CSV
Export
export_debug_data(path := "user://debug_export.txt", format := -1) -> bool
auto_export_path: String
auto_export_format: int
auto_export_interval: float
Lifecycle / introspection
static instance() -> Node # finds the autoload / bootstrap instance
attach_to_main_loop() -> void # for pure-instance mode
get_perf_stats() -> Dictionary
prune_stale_widgets() -> int
Signals
panel_registered(panel_name: String)
panel_unregistered(panel_name: String)
global_visibility_toggled(is_visible: bool)
monitor_enabled(monitor_id: String)
monitor_disabled(monitor_id: String)
data_exported(filepath: String, format: int)
DebugPanel extends Control
add_text_widget(section, label, getter, format := "%s") -> DebugWidgets.TextWidget
add_progress_widget(section, label, getter, min := 0.0, max := 1.0) -> DebugWidgets.ProgressWidget
add_graph_widget(section, label, getter, history_size := 30) -> DebugWidgets.GraphWidget
add_conditional_widget(section, label, getter, condition, true_text := "✓", false_text := "✗") -> DebugWidgets.ConditionalWidget
add_colored_widget(section, label, getter, ranges := [], format := "%s") -> DebugWidgets.ColoredWidget
add_timer_widget(section, label, timer, show_max := true) -> DebugWidgets.TimerWidget
add_vector_widget(section, label, getter, format := "(%.1f, %.1f)") -> DebugWidgets.VectorWidget
add_monitor(monitor: Dictionary) -> Object # metadata-driven dispatch
add_section(title: String) -> VBoxContainer
remove_widget(widget) -> void
clear() -> void
update_display() -> void
get_text_export() -> String
get_data_snapshot() -> Dictionary
# Sections
toggle_section_collapse(section_name: String) -> void
collapse_all_sections() -> void
expand_all_sections() -> void
# Theming / fonts
apply_font(font: Font) -> void
# Stats
widget_count() -> int
prune_stale() -> int
# Anchor constants
ANCHOR_TOP_LEFT, ANCHOR_TOP_RIGHT, ANCHOR_BOTTOM_LEFT, ANCHOR_BOTTOM_RIGHT,
ANCHOR_TOP_CENTER, ANCHOR_BOTTOM_CENTER, ANCHOR_CENTER, ANCHOR_FREE
DebugBootstrap extends Node
@export var quick_preset: int # enum
@export var settings: DebugSettings
@export var auto_apply: bool
@export var verbose: bool
var api: Node # the resolved DebugAPI
apply() -> void
reapply() -> void
DebugMonitors (RefCounted, static)
static get_registry() -> Dictionary
static get_monitor(id: String) -> Dictionary
static has_monitor(id: String) -> bool
static get_categories() -> Array
static get_monitors_by_category(category: String) -> Array
static get_preset_names() -> Array
static resolve_preset(preset_name: String) -> Array
static get_all_ids() -> Array
static sort_ids_by_category(ids: Array) -> Array
static register_custom_monitor(monitor: Dictionary) -> bool
static tick() -> void # internal — called by DebugAPI._process
DebugThemes (RefCounted, static)
static has_theme(name: String) -> bool
static get_theme(name: String) -> Dictionary
static get_theme_by_index(idx: int) -> Dictionary
static get_names() -> Array
DebugSettings extends Resource
See Configuration Reference. Helpers:
to_panel_config() -> Dictionary
collect_monitor_ids() -> Array
🔄 Migration from v0.x
If you used a pre-1.0 layout (files at res://, single example):
- Move every
.gdtores://addons/debug_api/. - Add
plugin.cfgandplugin.gd(provided in v1.0). Enable the plugin. - Remove
class_name DebugAPIfrom your DebugAPI.gd (the plugin handles this for you in v1.0). The old code that didvar api = DebugAPI.new()becomes:
…or just rely on the autoload:const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd") var api := DebugAPIScript.new()DebugAPI.method(). - Replace ad-hoc Label/Timer code with
DebugAPI.enable_monitor_preset("essential")and custom-paneladd_*_widgetcalls. - The old
panel.vis = boolfield is gone. Usepanel.visible = bool(Control's standard property).
Performance and ergonomics improvements come for free after the move.
🇪🇸 Español
📋 Índice
- Introducción
- Características
- Arquitectura
- Instalación — cuatro modos
- Inicio rápido (60 segundos)
- Tutorial paso a paso
- Catálogo de monitores integrados
- Paneles personalizados y widgets
- Referencia de widgets
- Temas
- Referencia de configuración (DebugSettings)
- Atajos y acciones de input
- Exportación y persistencia
- Notas de rendimiento
- Solución de problemas
- Referencia de API
- Migración desde v0.x
🎮 Introducción
Debug API convierte el código repetitivo de "mostrar FPS, mostrar esta variable, mostrar ese timer" en una declaración de una línea. Copias el addon, activas el plugin y obtienes:
- ~50 monitores integrados (FPS, frame time, memoria, GPU, draw calls, físicas, scene tree, audio, red, info de sistema, ...) que activas individualmente, por categoría o con presets con nombre.
- Una API declarativa de widgets para tus variables — vinculas un valor a un
TextWidget/ProgressWidget/GraphWidget/ etc. y se actualiza solo. - Configuración desde el inspector mediante un recurso
DebugSettings— cada opción también está expuesta por código. - Temas, anclajes, secciones colapsables, tipografía custom, barra de título opcional, click-through, hotkeys vía acciones de
InputMap, exportación JSON/CSV/TXT, auto-export por intervalo, persistencia de snapshots, inicialización condicional sólo en debug. - Smart-diff y rate-limit por widget para que un preset completo se mantenga por debajo de 1 ms/frame con 50 widgets.
Versión:
v1.0· Motor: Godot 4.0+ · Lenguaje: GDScript · Tipo: Plugin (autoload + Resource + nodo Bootstrap)
El problema. Cada proyecto reimplementa Label + _process para mostrar FPS, luego variables, luego timers. Muchos CanvasLayer, código de formato, manejo de hotkeys.
La solución. Una API central que se encarga del renderizado y te deja declarar qué mostrar, no cómo mostrarlo.
✨ Características
| Categoría | Lo que obtienes |
|---|---|
| Monitores integrados | FPS (actual/avg/min/max/gráfica), frame time, process time, physics process, navigation process, memoria estática + pico, message queue, video memory, texture memory, buffer memory, total objects, node count, resource count, orphan nodes, render objects/primitives/draw calls, GPU name/vendor/type, rendering method, físicas 2D/3D bodies/pairs/islands, audio latency, window/screen size/position/DPI/refresh rate, aspect ratio, fullscreen/window mode/vsync, OS, CPU, núcleos, arquitectura, versión del engine, locale, debug flag, time scale, physics tps, uptime, hora del sistema, posición del ratón, joypads, escena actual, conteo de nodos, multiplayer ID, peers. |
| Widgets | Texto, barra de progreso, gráfica (con historial), condicional (booleano), coloreado (umbrales), Timer, Vector. |
| Presets | minimal, essential, performance, memory, rendering, system, display, full. |
| Temas | Default, Dark, Light, Neon, Retro, Minimal, Solarized + custom completo. |
| Layout | 8 anclajes (esquinas, top/bottom centre, centre, libre), márgenes al borde, padding, radio de esquina, borde, tipografía custom, barra de título opcional, scroll cuando el contenido excede max_height. |
| Comportamiento | Secciones colapsables, click-through, toggle por panel (key + acción de InputMap), toggle global, hotkey de export, auto-export cada N s, sólo en debug, modo pausado. |
| Exportación | TXT (default), JSON, CSV — autodetección por extensión. |
| Persistencia | save_settings(...) / load_settings(...) / snapshot_settings() — round-trip de tus customizaciones a un .tres. |
| Auto-config | Coloca res://debug_settings.tres y se aplica en _ready — sin código. |
| Rendimiento | Smart-diff (no asigna Label.text si el valor no cambió), update_interval por widget, salta widgets ocultos, pausa instantánea, get_perf_stats(). |
| Compatibilidad | Godot 4.0+, headless-safe, renderers Forward+ / Mobile / Compatibility, multi-plataforma. |
🏗️ Arquitectura
DebugAPI (autoload o gestionado por DebugBootstrap)
│
├── _process() ── DebugMonitors.tick() (1 float/frame para historial de FPS)
│
├── Panel auto ── "__auto__" (los monitores integrados viven aquí)
│ └── secciones por categoría (Performance, Memory, Display, ...)
│
└── Paneles custom (tu código)
└── DebugPanel ─ secciones ─ widgets
│
├── TextWidget
├── ProgressWidget
├── GraphWidget
├── ConditionalWidget
├── ColoredWidget
├── TimerWidget
└── VectorWidget
res://addons/debug_api/
├── plugin.cfg # manifest del plugin
├── plugin.gd # EditorPlugin (registra el autoload "DebugAPI")
├── DebugAPI.gd # entrada principal (SIN class_name — el autoload usa el nombre)
├── DebugPanel.gd # panel que aloja widgets
├── DebugWidgets.gd # clases de widgets (Text, Progress, Graph, ...)
├── DebugMonitors.gd # registro de monitores integrados
├── DebugThemes.gd # presets de color con nombre
├── DebugSettings.gd # Resource — la vía "configurar desde inspector"
├── DebugBootstrap.gd # nodo drop-in para proyectos sin autoloads
└── examples/
├── DebugExample.gd # panel custom + auto-monitores
├── AutoMonitorsExample.gd # demo mínima de auto-monitores
├── BootstrapExample.gd # setup sin autoload
└── AdvancedConfigExample.gd # temas, hotkeys, export JSON, panel scrollable
📦 Instalación — cuatro modos
Escoge uno. Todos son aptos para producción.
① Plugin — recomendado
- Copia
addons/debug_api/al directoriores://addons/de tu proyecto. - Project Settings → Plugins → Debug API → activar.
- Úsalo en cualquier sitio:
func _ready(): DebugAPI.enable_monitor_preset("essential")
El plugin registra un autoload llamado DebugAPI. El script DebugAPI.gd deliberadamente no tiene class_name — su nombre está reservado para el autoload (Godot 4.4+ rechaza que class_name y autoload compartan nombre).
② Autoload manual
Si prefieres no usar el plugin (por ejemplo en CI o headless), registra el autoload tú mismo:
- Project Settings → Autoload → Path:
res://addons/debug_api/DebugAPI.gd, Name:DebugAPI→ Add.
Mismo código que el método ①.
③ Nodo Bootstrap — sin autoload
Arrastra un nodo DebugBootstrap a tu escena principal. Desde el inspector:
- o eliges un
quick_preset(none / minimal / essential / performance / memory / rendering / system / display / full), - o asignas un recurso
DebugSettings.trespara control completo.
Acceso desde código vía bootstrap.api. Ideal para librerías, plugins de plugins o proyectos que evitan los autoloads por convención.
④ Instancia pura / modo librería
Para tests, contextos embebidos o máximo desacoplamiento:
const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd")
var api := DebugAPIScript.new()
add_child(api)
api.enable_monitor("fps")
DebugAPI.gd no tiene class_name, así que llegas a él por preload(...). Todo lo demás (DebugPanel, DebugSettings, DebugMonitors, DebugThemes, DebugWidgets, DebugBootstrap) sí tiene class_name — los referencias directamente.
🚀 Inicio rápido (60 segundos)
Tras instalar el plugin (método ①):
extends Node
func _ready():
DebugAPI.enable_monitor_preset("essential")
Ejecuta el proyecto. El panel muestra FPS, frame time, memoria estática, conteo de nodos y tamaño de ventana. Pulsa F1 para ocultar/mostrar.
¿Todo?
DebugAPI.enable_all_monitors()
¿Sólo FPS?
DebugAPI.enable_monitor("fps")
¿Otro look?
DebugAPI.apply_theme("neon")
Listo. Sigue leyendo para el tour completo.
📖 Tutorial paso a paso
Paso 1 — Instalar
Copia addons/debug_api/ a tu proyecto. Activa el plugin en Project Settings → Plugins.
No deberías ver errores en el panel de Output, y un nuevo autoload "DebugAPI" debe aparecer en Project Settings → Autoload.
Paso 2 — Tu primera métrica
En cualquier script:
extends Node
func _ready():
DebugAPI.enable_monitor("fps")
Ejecuta. Aparece el contador de FPS arriba a la izquierda. F1 oculta/muestra.
Paso 3 — Elegir un preset
Cambia la llamada por:
DebugAPI.enable_monitor_preset("performance")
Ahora ves FPS, FPS promedio, mín, máx, frame time, process time y physics process. Otros presets:
"minimal" → solo FPS
"essential" → FPS, frame time, memoria, nodos, tamaño de ventana
"performance" → familia FPS, frame time, process times
"memory" → estática, pico, video, textura, buffer, huérfanos
"rendering" → objetos, primitives, draw calls, info GPU
"system" → OS, CPU, núcleos, GPU, versión engine
"display" → tamaño de ventana/pantalla, DPI, refresh, fullscreen, vsync
"full" → todo (~50 widgets)
También puedes activar una categoría entera:
DebugAPI.enable_monitor_category("memory")
Paso 4 — Configurar desde el inspector
La configuración por código está bien, pero para "configurar y olvidar" puedes manejar todo desde un recurso DebugSettings.
- En la pestaña FileSystem, click derecho → Nuevo Recurso… → busca DebugSettings → Crear.
- Guárdalo como
res://debug_settings.tres. - Ábrelo. El inspector muestra grupos: Quick Setup, By Category, Specific Monitors, Position, Panel Behavior, Hotkeys, Panel Layout, Title Bar, Style, Export.
- Marca las categorías que quieras. Ajusta colores, hotkey, anclaje — lo que prefieras.
- Ejecuta el proyecto.
DebugAPIcarga automáticamenteres://debug_settings.tresen_readyy lo aplica. Sin código.
Si prefieres otro nombre de fichero o aplicarlo bajo demanda:
var settings: DebugSettings = load("res://my_settings.tres")
DebugAPI.apply_settings(settings)
La auto-carga también busca en res://addons/debug_api/debug_settings.tres y user://debug_settings.tres.
Paso 5 — Widgets custom
Los monitores integrados cubren el estado del engine. Para tu estado, construye un panel:
extends CharacterBody2D
var health: float = 100.0
var coyote_timer: Timer
var debug_panel: DebugPanel
func _ready():
coyote_timer = Timer.new()
coyote_timer.wait_time = 0.12
coyote_timer.one_shot = true
add_child(coyote_timer)
debug_panel = DebugAPI.create_panel("Player", self, {
"anchor": DebugPanel.ANCHOR_TOP_RIGHT,
"edge_margin": Vector2(8, 8),
})
debug_panel.add_text_widget("STATE", "Position", func(): return global_position, "(%.0f, %.0f)")
debug_panel.add_progress_widget("STATE", "Health", func(): return health, 0.0, 100.0)
debug_panel.add_timer_widget("TIMERS", "Coyote", coyote_timer)
debug_panel.add_conditional_widget("STATE", "Grounded",
func(): return is_on_floor(), func(v): return v, "🟢 SI", "🔴 NO")
El panel se actualiza solo cada frame. El panel Player tiene su propia tecla de toggle (F1 por defecto, configurable en el dict de config).
Paso 6 — Aplicar un tema
DebugAPI.apply_theme("dark")
Disponibles: default, dark, light, neon, retro, minimal, solarized. El tema reemplaza los colores del panel auto; tus monitores siguen activos y se reestilizan al instante.
Desde el inspector, pon theme_preset en DebugSettings a cualquier valor distinto de Custom y los selectores de color individuales se ignoran (el tema gana).
Paso 7 — Hotkey de exportación
DebugAPI.export_hotkey = KEY_F3
DebugAPI.export_path = "user://debug.json"
DebugAPI.export_format = DebugAPI.EXPORT_JSON
Pulsa F3 en el juego y el estado actual de cada panel se escribe en user://debug.json. La autodetección por extensión también funciona:
DebugAPI.export_debug_data("user://snapshot.csv") # → CSV
DebugAPI.export_debug_data("user://snapshot.json") # → JSON
DebugAPI.export_debug_data("user://snapshot.txt") # → TXT
Para snapshots periódicos:
DebugAPI.auto_export_path = "user://logs/auto.json"
DebugAPI.auto_export_format = DebugAPI.EXPORT_JSON
DebugAPI.auto_export_interval = 30.0 # cada 30 s
Paso 8 — Persistir tus customizaciones
Has pasado diez minutos retocando colores, hotkey, layout. Guarda el resultado:
var snap := DebugAPI.snapshot_settings()
DebugAPI.save_settings(snap, "user://my_debug.tres")
En el próximo arranque:
var loaded := DebugAPI.load_settings("user://my_debug.tres")
if loaded:
DebugAPI.apply_settings(loaded)
O distribuye el .tres con tu proyecto en res://debug_settings.tres y la auto-carga lo gestiona.
Eso es todo el tour. Las secciones siguientes son material de referencia.
📊 Catálogo de monitores integrados
Cada monitor tiene un id estable. Úsalo con enable_monitor(id) o inclúyelo en DebugSettings.monitor_ids.
Performance — category: "performance"
| id | etiqueta | widget | refresco |
|---|---|---|---|
fps |
FPS | colored | cada frame |
fps_avg |
Avg FPS | colored | cada frame |
fps_min |
Min FPS | colored | cada frame |
fps_max |
Max FPS | text | cada frame |
frame_time |
Frame Time | colored (ms) | cada frame |
process_time |
Process Time | text | cada frame |
physics_process_time |
Physics Process | text | cada frame |
navigation_process_time |
Navigation Process | text | cada frame |
fps_graph |
FPS Graph | graph | cada frame |
Memory — category: "memory"
memory_static, memory_static_max, message_queue_max, video_memory, texture_memory, buffer_memory. Todos formato humanizado (KiB / MiB), refresco cada frame.
Objects — category: "objects"
object_count, node_count, resource_count, orphan_nodes (con umbrales de color: verde 0, ámbar < 10, rojo ≥ 10).
Rendering — category: "rendering"
| id | etiqueta | refresco |
|---|---|---|
total_objects / total_primitives / total_draw_calls |
contadores por frame | cada frame |
rendering_method |
método de render | cada 60 s |
gpu_name / gpu_vendor / gpu_type |
información GPU | cada 60 s |
Physics — category: "physics"
active_bodies_2d, collision_pairs_2d, physics_islands_2d, active_bodies_3d, collision_pairs_3d, physics_islands_3d. Todos int, refresco cada frame.
Audio — category: "audio"
audio_latency — float ms, refresco cada 1 s.
Display — category: "display"
window_size, window_position, screen_size, screen_dpi, screen_refresh_rate, aspect_ratio, fullscreen (conditional), window_mode, vsync_mode. Refresco 0.5 – 5 s según métrica.
System — category: "system"
os_name, os_version, cpu_model, cpu_cores, architecture, engine_version, locale, debug_build. La mayoría refresca cada 60 s (valores prácticamente inmutables).
Time — category: "time"
time_scale (cada frame), physics_ticks_per_second (5 s), uptime (1 s), system_time (0.5 s).
Input — category: "input"
mouse_position (vector, cada frame), joypad_count (0.5 s).
Scene — category: "scene"
current_scene (1 s), scene_tree_node_count (0.2 s).
Network — category: "network"
multiplayer_id (1 s), multiplayer_peers (0.5 s).
Monitores custom
Registra los tuyos en runtime:
DebugAPI.register_custom_monitor({
"id": "frames_drawn",
"label": "Frames Drawn",
"category": "performance",
"widget_type": "text",
"format": "%d",
"getter": func(): return Engine.get_frames_drawn(),
})
DebugAPI.enable_monitor("frames_drawn")
Claves opcionales: update_interval (s), color_ranges (para widgets "colored"), condition / true_text / false_text (para "conditional"), history_size (para "graph"), min / max (para "progress").
🎨 Paneles personalizados y widgets
DebugAPI.create_panel(name, parent, config) crea un panel nuevo:
var panel := DebugAPI.create_panel("AI", get_tree().current_scene, {
"anchor": DebugPanel.ANCHOR_BOTTOM_RIGHT,
"edge_margin": Vector2(8, 8),
"min_width": 240,
"max_height": 400, # scroll si excede
"panel_padding": 8,
"corner_radius": 6,
"show_title": true,
"title_text": "AI Brain",
"collapsible_sections": true,
"toggle_key": KEY_F4,
"background_color": Color(0, 0.05, 0.1, 0.9),
})
El panel se mete en un CanvasLayer colocado bajo parent. Las teclas de toggle son por panel, así que múltiples paneles pueden coexistir con shortcuts distintos.
Añade widgets con los métodos dedicados (ver Referencia de widgets) o con add_monitor(monitor_dict) para un flujo dirigido por metadatos similar a los monitores integrados.
Múltiples paneles:
DebugAPI.create_panel("Player", player_node, {"anchor": DebugPanel.ANCHOR_TOP_LEFT})
DebugAPI.create_panel("Enemy", enemy_node, {"anchor": DebugPanel.ANCHOR_TOP_RIGHT})
DebugAPI.create_panel("World", world_node, {"anchor": DebugPanel.ANCHOR_BOTTOM_LEFT})
Cada uno tiene su toggle. Usa DebugAPI.toggle_global_visibility() (o asigna global_toggle_key) para ocultar/mostrar todos a la vez.
🔧 Referencia de widgets
Todos los creadores devuelven la instancia para que la guardes y modifiques después.
TextWidget
panel.add_text_widget(section, label, getter, format := "%s")
"clave: valor" simple. Smart-diff evita re-renderizar cuando el valor no cambia.
ProgressWidget
panel.add_progress_widget(section, label, getter, min := 0.0, max := 1.0)
Barra con etiqueta de porcentaje.
GraphWidget
panel.add_graph_widget(section, label, getter, history_size := 30)
Gráfica de línea con historial. Se redibuja cada update.
ConditionalWidget
panel.add_conditional_widget(section, label, getter, condition,
true_text := "✓", false_text := "✗")
Estado booleano con color distinto en cada rama.
ColoredWidget
panel.add_colored_widget(section, label, getter, ranges := [], format := "%s")
Color por umbral. Cada rango es {"condition": Callable(value) -> bool, "color": Color}. Gana el primero que cumpla.
TimerWidget
panel.add_timer_widget(section, label, timer: Timer, show_max := true)
Visualiza un nodo Timer — time_left / wait_time.
VectorWidget
panel.add_vector_widget(section, label, getter, format := "(%.1f, %.1f)")
Auto-formatea Vector2 y Vector3.
update_interval por widget
Tras la creación:
var w := panel.add_text_widget("INFO", "GPU", func(): return RenderingServer.get_video_adapter_name())
w.update_interval = 60.0 # refresca una vez por minuto
Para monitores integrados a nivel API:
DebugAPI.set_monitor_update_interval("orphan_nodes", 0.5)
Eliminar widgets
panel.remove_widget(my_widget)
panel.clear() # todos los widgets del panel
DebugAPI.disable_monitor("fps")
DebugAPI.disable_all_monitors()
🎨 Temas
| Tema | Caso de uso |
|---|---|
| Default | Negro translúcido, etiquetas azul suave. Default amigable para producción. |
| Dark | Fondo casi negro sólido, texto de alto contraste. Bueno para streaming. |
| Light | Fondo blanco roto, texto azul marino. UIs de día / temas claros. |
| Neon | Estilo cyber: fondo oscuro, acentos verde eléctrico/magenta. |
| Retro | Sensación de terminal: ámbar sobre verde oscuro, headers verde brillante. |
| Minimal | Fondo transparente, texto blanco. Overlay sobre UI existente sin peso visual. |
| Solarized | Paleta Solarized-Dark. Cómodo para sesiones largas. |
Aplica por nombre desde código:
DebugAPI.apply_theme("solarized")
O configura theme_preset en DebugSettings (cualquier valor distinto de Custom reemplaza los colores individuales).
⚙️ Referencia de configuración (DebugSettings)
Cada propiedad es @export. Los grupos del inspector están en negrita.
| Propiedad | Tipo | Default | Propósito |
|---|---|---|---|
| Quick setup | |||
preset |
int (enum) | none |
Aplica un preset de monitores. |
theme_preset |
int (enum) | Default |
Tema integrado. Custom usa los colores individuales. |
only_in_debug_build |
bool | false |
Salta init en builds de release. |
| By Category | |||
enable_performance … enable_network |
bool | false |
Activa todos los monitores de esa categoría. |
| Specific Monitors | |||
monitor_ids |
Array[String] | [] |
Ids extra encima del preset/categorías. |
| Position | |||
anchor |
int (enum) | Top Left |
Dónde se coloca el panel. Free usa free_position. |
edge_margin |
Vector2 | (8, 8) |
Distancia desde el borde anclado. |
free_position |
Vector2 | (8, 8) |
Sólo cuando anchor = Free. |
| Panel Behavior | |||
start_visible |
bool | true |
Visibilidad inicial. |
update_interval |
float | 0.0 |
Throttle global del panel (s). 0 = cada frame. |
click_through |
bool | true |
Si true, el panel no captura clicks. |
collapsible_sections |
bool | false |
Las cabeceras de sección se vuelven botones que pliegan. |
| Hotkeys | |||
toggle_key |
int (Key) | KEY_F1 |
Toggle por panel. KEY_NONE desactiva. |
toggle_action |
String | "" |
Nombre de acción de InputMap (prioridad sobre keycode). |
global_toggle_key |
int | KEY_NONE |
Oculta todos los paneles. |
global_toggle_action |
String | "" |
Versión InputMap. |
export_hotkey |
int | KEY_NONE |
Dispara export_debug_data. |
export_action |
String | "" |
Versión InputMap. |
| Panel Layout | |||
min_width |
int | 250 |
Ancho mínimo. |
max_height |
float | 0.0 |
Cuando > 0 el panel es scrollable. |
canvas_layer |
int | 100 |
Índice del CanvasLayer. |
spacing |
int | 4 |
Píxeles entre filas. |
panel_padding |
int | 6 |
Padding interno. |
border_width |
int | 1 |
0 = sin borde. |
corner_radius |
int | 0 |
Esquinas redondeadas. |
| Title Bar | |||
show_title |
bool | false |
Título centrado sobre las secciones. |
title_text |
String | "" |
Cae al nombre del panel si vacío. |
| Style (sólo cuando theme_preset = Custom) | |||
background_color, border_color, font_color, section_color, title_color, value_color, shadow_color, shadow_offset, font_size, custom_font |
Color/Vector2/int/Font | colores por defecto | Personalización completa. |
| Export | |||
export_path |
String | user://debug_export.txt |
Destino del export por hotkey. |
export_format |
int (enum) | TXT |
TXT / JSON / CSV. |
auto_export_interval |
float | 0.0 |
0 = desactivado. |
auto_export_path |
String | "" |
Destino del auto-export. |
auto_export_format |
int (enum) | TXT |
TXT / JSON / CSV. |
Cada export también es un campo público en la API o una clave del dict config del panel. DebugSettings.to_panel_config() hace la conversión por debajo.
⌨️ Atajos y acciones de input
Dos capas:
- Por panel — cada
DebugPaneltiene sutoggle_key(defaultKEY_F1) y untoggle_actionopcional. Cuando ambos están definidos, la acción gana sobre el keycode. - Globales en
DebugAPI—global_toggle_key/global_toggle_actionocultan todos los paneles;export_hotkey/export_actionescriben un snapshot aexport_path.
Usa acciones de InputMap cuando tu proyecto ya gestiona input remappable. Ejemplo:
- Project Settings → Input Map → New action
debug_toggle→ bind a F1. - En código:
var settings := DebugSettings.new() settings.toggle_action = "debug_toggle" DebugAPI.apply_settings(settings)
Pon toggle_key = KEY_NONE y toggle_action = "" para desactivar el hotkey de un panel.
Evita el doble-handling: no pongas
global_toggle_keyigual quetoggle_keyde un panel — el evento dispara ambos handlers y la visibilidad rebota.
💾 Exportación y persistencia
Exportar el estado actual
DebugAPI.export_debug_data() # path/format por defecto
DebugAPI.export_debug_data("user://snap.json") # autodetección por extensión
DebugAPI.export_debug_data("user://snap.csv", DebugAPI.EXPORT_CSV)
La señal data_exported(filepath, format) se emite al éxito.
Auto-export
DebugAPI.auto_export_path = "user://logs/auto.json"
DebugAPI.auto_export_format = DebugAPI.EXPORT_JSON
DebugAPI.auto_export_interval = 30.0
Pon auto_export_interval = 0.0 para detener.
Persistir tus customizaciones como Resource
# Guardar el estado actual
var s := DebugAPI.snapshot_settings()
DebugAPI.save_settings(s, "user://my_debug.tres")
# Restaurar
var loaded := DebugAPI.load_settings("user://my_debug.tres")
if loaded:
DebugAPI.apply_settings(loaded)
Auto-carga de un settings .tres en arranque
Coloca un recurso DebugSettings en cualquiera de los paths siguientes y _ready lo aplica automáticamente:
res://debug_settings.tresres://addons/debug_api/debug_settings.tresuser://debug_settings.tres
Si ya has llamado a apply_settings(...) explícitamente, la auto-carga se salta a sí misma (para que DebugBootstrap gane).
⚡ Notas de rendimiento
- Smart-diff — cada widget de texto compara el valor nuevo con el anterior y salta el
Label.textsi no cambió. El coste dominante en bucles cerrados desaparece. update_intervalpor widget — los monitores integrados llevan tags. Estáticos comogpu_namese actualizan una vez por minuto; metadatos de ventana/pantalla a 0.5–1 Hz; métricas por frame siguen cada frame. Configura más conDebugAPI.set_monitor_update_interval(id, seconds)owidget.update_interval = ….- Widgets ocultos saltados —
update_display()revisais_visible_in_tree()y ignora widgets en secciones plegadas o paneles ocultos. - Pausa —
DebugAPI.paused = truedetiene el sampler de FPS, el_processde cada panel y el tick de auto-export.paused = falsereanuda. Switch on/off barato. - Inicialización condicional —
DebugSettings.only_in_debug_build = truehace queapply_settingssea no-op en builds no-debug. Cero overhead en producción. - Introspección —
DebugAPI.get_perf_stats()devuelve{panels, total_widgets, enabled_monitors, fps_history_size, paused, only_in_debug}.
Un preset "full" (~50 widgets) a 60 Hz con smart-diff y throttling por widget cuesta típicamente menos de 0.5 ms/frame en escritorio.
🩺 Solución de problemas
"Nombre inválido. No debe colisionar con un nombre de clase de script global existente."
Tienes un class_name DebugAPI y a la vez intentas registrar un autoload llamado DebugAPI. Godot 4.4+ rechaza esto. Solución: asegúrate de que DebugAPI.gd no declara class_name. El plugin / autoload se queda con el nombre.
"Cannot call non-static function on the class 'DebugAPI' directly. Make an instance instead."
Misma raíz que arriba — DebugAPI resuelve al tipo de clase en vez de a la instancia del autoload. Quita class_name DebugAPI, reactiva el plugin.
Errores con paths como res://addons/debug_api/addons/debug_api/...
Tienes una carpeta del addon duplicada/anidada O Godot ha cacheado paths viejos. Arreglo:
- Cierra Godot.
- Verifica que
res://addons/debug_api/no contiene otra subcarpetaaddons/. Si la tiene, bórrala. - Borra la carpeta
.godot/del proyecto (Godot la regenera). - Reabre el proyecto y deja que termine de escanear.
DebugSettings no aparece en Nuevo Recurso → Debug…
Casi siempre el mismo problema de caché obsoleta. Borra .godot/ y reabre. Si sigue sin aparecer, abre DebugSettings.gd y confirma que tiene @tool, class_name DebugSettings, extends Resource.
La auto-carga de debug_settings.tres no hace nada
Tres comprobaciones:
- El fichero existe en uno de los paths y es un recurso
DebugSettingsreal (no un.tresgenérico). - No has llamado
apply_settings(...)antes — la auto-carga se salta intencionadamente tras un apply explícito. only_in_debug_build = truey estás en build de release.
Para forzar reescaneo: DebugAPI.reload_auto_settings().
Los monitores de display muestran 0
Build headless — DisplayServer devuelve ceros. Desactiva la categoría display en tus settings si te molesta.
El panel bloquea el input del juego
Pon click_through = true (default en v1.0). Los botones internos siguen recibiendo sus clicks porque mouse_filter es por Control.
📚 Referencia de API
Misma superficie que la sección inglesa. Resumido:
DebugAPI—enable_monitor*,disable_monitor*,list_*,register_custom_monitor,set_monitor_update_interval,create_panel,get_panel,remove_panel,apply_settings,apply_theme,snapshot_settings,save_settings/load_settings(estáticos),export_debug_data,toggle_global_visibility,paused,instance()(estático),attach_to_main_loop,get_perf_stats,prune_stale_widgets,reload_auto_settings. Señales:panel_registered,panel_unregistered,global_visibility_toggled,monitor_enabled,monitor_disabled,data_exported.DebugPanel(extends Control) —add_text_widget,add_progress_widget,add_graph_widget,add_conditional_widget,add_colored_widget,add_timer_widget,add_vector_widget,add_monitor,add_section,remove_widget,clear,update_display,get_text_export,get_data_snapshot,toggle_section_collapse,collapse_all_sections,expand_all_sections,apply_font,widget_count,prune_stale. ConstantesANCHOR_*.DebugBootstrap(extends Node) — exportsquick_preset,settings,auto_apply,verbose. Var públicaapi. Métodosapply(),reapply().DebugMonitors(RefCounted, estático) —get_registry,get_monitor,has_monitor,get_categories,get_monitors_by_category,get_preset_names,resolve_preset,get_all_ids,sort_ids_by_category,register_custom_monitor,tick.DebugThemes(RefCounted, estático) —has_theme,get_theme,get_theme_by_index,get_names.DebugSettings(Resource) — todas las propiedades exportadas (ver tabla). Helpersto_panel_config()ycollect_monitor_ids().
🔄 Migración desde v0.x
Si usabas un layout pre-1.0 (ficheros en res://, ejemplo único):
- Mueve cada
.gdares://addons/debug_api/. - Añade
plugin.cfgyplugin.gd(incluidos en v1.0). Activa el plugin. - Elimina
class_name DebugAPIde tu DebugAPI.gd (en v1.0 lo manejamos así para no chocar con el autoload). El antiguovar api = DebugAPI.new()pasa a:
…o simplemente confía en el autoload:const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd") var api := DebugAPIScript.new()DebugAPI.method(). - Reemplaza el código ad-hoc de Label/Timer por
DebugAPI.enable_monitor_preset("essential")y llamadasadd_*_widgeten paneles custom. - La propiedad antigua
panel.vis = boolya no existe. Usapanel.visible = bool(la propiedad estándar de Control).
Las mejoras de rendimiento y ergonomía vienen gratis tras el movimiento.
🇫🇷 Français
Présentation
Debug API transforme le code répétitif de « afficher les FPS, afficher cette variable, afficher ce timer » en une déclaration d'une ligne. Le module fournit :
- ~50 moniteurs intégrés (FPS, temps de frame, mémoire, GPU, draw calls, physiques, scene tree, audio, réseau, infos système, ...).
- Une API de widgets pour vos propres variables — vous liez une valeur à un
TextWidget/ProgressWidget/GraphWidget/ etc. - Configuration depuis l'inspecteur via un Resource
DebugSettings. - Thèmes, ancres, sections rabattables, polices personnalisées, hotkeys via actions
InputMap, export JSON/CSV/TXT, snapshots persistants. - Smart-diff et rate-limit par widget pour rester sous 1 ms/frame avec 50+ widgets.
Version :
v1.0· Moteur : Godot 4.0+ · Type : Plugin (autoload + Resource + nœud Bootstrap)
Installation
① Plugin (recommandé)
- Copiez
addons/debug_api/dansres://addons/de votre projet. - Project Settings → Plugins → Debug API → activer.
- Utilisez :
func _ready(): DebugAPI.enable_monitor_preset("essential")
Le plugin enregistre un autoload nommé DebugAPI. Le script DebugAPI.gd n'a délibérément pas de class_name — son nom est réservé à l'autoload.
② Autoload manuel
Project Settings → Autoload → chemin res://addons/debug_api/DebugAPI.gd, nom DebugAPI.
③ Nœud Bootstrap (sans autoload)
Glissez un nœud DebugBootstrap dans votre scène principale et configurez via l'inspecteur.
④ Instance pure
const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd")
var api := DebugAPIScript.new()
add_child(api)
api.enable_monitor("fps")
Démarrage rapide
extends Node
func _ready():
DebugAPI.enable_monitor_preset("essential")
F1 affiche/masque le panneau. apply_theme("neon") change le thème. register_custom_monitor({...}) ajoute vos métriques.
Configuration zéro-code
Déposez un fichier DebugSettings.tres à res://debug_settings.tres et il est appliqué au démarrage. Aucun code requis.
Pour la documentation détaillée
Consultez la section 🇬🇧 English ci-dessus pour le tutoriel pas-à-pas, le catalogue des moniteurs, la référence des widgets, des thèmes, du DebugSettings, des hotkeys, de l'export, des notes de performance, du troubleshooting et de l'API complète.
🇩🇪 Deutsch
Überblick
Debug API verwandelt das wiederholte „FPS anzeigen, diese Variable anzeigen, diesen Timer anzeigen" in eine Einzeiler-Deklaration. Das Modul bietet:
- ~50 eingebaute Monitore (FPS, Frame Time, Speicher, GPU, Draw Calls, Physik, Scene-Tree, Audio, Netzwerk, Systeminfo, ...).
- Eine Widget-API für eigene Variablen — Sie binden einen Wert an ein
TextWidget/ProgressWidget/GraphWidget/ etc. - Inspector-Konfiguration über eine
DebugSettings-Ressource. - Themes, Anker, einklappbare Sektionen, eigene Schriftarten, Hotkeys über
InputMap-Actions, Export JSON/CSV/TXT, persistente Snapshots. - Smart-Diff und Per-Widget-Rate-Limit — bleibt unter 1 ms/Frame bei 50+ Widgets.
Version:
v1.0· Engine: Godot 4.0+ · Typ: Plugin (Autoload + Resource + Bootstrap-Node)
Installation
① Plugin (empfohlen)
- Kopieren Sie
addons/debug_api/nachres://addons/. - Project Settings → Plugins → Debug API → aktivieren.
- Verwenden:
func _ready(): DebugAPI.enable_monitor_preset("essential")
Das Plugin registriert einen Autoload namens DebugAPI. Das Skript DebugAPI.gd hat absichtlich kein class_name — der Name ist für den Autoload reserviert.
② Manueller Autoload
Project Settings → Autoload → Pfad res://addons/debug_api/DebugAPI.gd, Name DebugAPI.
③ Bootstrap-Node (ohne Autoload)
Ziehen Sie einen DebugBootstrap-Knoten in Ihre Hauptszene und konfigurieren Sie ihn im Inspector.
④ Reine Instanz
const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd")
var api := DebugAPIScript.new()
add_child(api)
api.enable_monitor("fps")
Schnellstart
extends Node
func _ready():
DebugAPI.enable_monitor_preset("essential")
F1 schaltet das Panel um. apply_theme("neon") ändert das Theme. register_custom_monitor({...}) fügt eigene Metriken hinzu.
Null-Code-Konfiguration
Legen Sie eine DebugSettings.tres-Datei unter res://debug_settings.tres ab — sie wird beim Start angewendet. Kein Code nötig.
Vollständige Dokumentation
Siehe Abschnitt 🇬🇧 English oben für das vollständige Tutorial, den Monitor-Katalog, die Widget-Referenz, Themes, DebugSettings-Referenz, Hotkeys, Export, Performance-Hinweise, Troubleshooting und die vollständige API-Referenz.
🇧🇷 Português
Visão geral
Debug API transforma o código repetitivo de "mostrar FPS, mostrar esta variável, mostrar esse timer" em uma declaração de uma linha. O módulo fornece:
- ~50 monitores integrados (FPS, frame time, memória, GPU, draw calls, físicas, scene tree, áudio, rede, info do sistema, ...).
- Uma API declarativa de widgets para suas próprias variáveis — você vincula um valor a um
TextWidget/ProgressWidget/GraphWidget/ etc. - Configuração via inspetor através de um Resource
DebugSettings. - Temas, âncoras, seções colapsáveis, fontes customizadas, hotkeys via ações de
InputMap, exportação JSON/CSV/TXT, persistência de snapshots. - Smart-diff e rate-limit por widget — fica abaixo de 1 ms/frame com 50+ widgets.
Versão:
v1.0· Engine: Godot 4.0+ · Tipo: Plugin (autoload + Resource + nó Bootstrap)
Instalação
① Plugin (recomendado)
- Copie
addons/debug_api/parares://addons/. - Project Settings → Plugins → Debug API → ativar.
- Use:
func _ready(): DebugAPI.enable_monitor_preset("essential")
O plugin registra um autoload chamado DebugAPI. O script DebugAPI.gd deliberadamente não possui class_name — o nome está reservado para o autoload.
② Autoload manual
Project Settings → Autoload → caminho res://addons/debug_api/DebugAPI.gd, nome DebugAPI.
③ Nó Bootstrap (sem autoload)
Arraste um nó DebugBootstrap para sua cena principal e configure pelo inspetor.
④ Instância pura
const DebugAPIScript = preload("res://addons/debug_api/DebugAPI.gd")
var api := DebugAPIScript.new()
add_child(api)
api.enable_monitor("fps")
Início rápido
extends Node
func _ready():
DebugAPI.enable_monitor_preset("essential")
F1 alterna o painel. apply_theme("neon") muda o tema. register_custom_monitor({...}) adiciona suas métricas.
Configuração sem código
Coloque um arquivo DebugSettings.tres em res://debug_settings.tres e ele será aplicado na inicialização. Nenhum código necessário.
Documentação detalhada
Consulte a seção 🇬🇧 English acima para o tutorial passo-a-passo completo, catálogo de monitores, referência de widgets, temas, referência do DebugSettings, hotkeys, exportação, notas de performance, troubleshooting e referência completa da API.
🤝 Contributing
Pull requests welcome. New monitors / themes / widgets are especially appreciated. Please follow the existing GDScript style (tabs, type-annotated public methods, smart-diff for new widgets) and add a short note to CHANGELOG.md.
📄 License & Attribution
Released under the MIT License — see LICENSE for the full
legal text. Free for any use, commercial or not. Modify, redistribute, embed
in your game — go ahead.
The MIT License only requires preserving the copyright notice in copies of
the source. Beyond that, attribution is a kind gesture rather than an
obligation: if this addon helps your project, a brief mention in your credits
screen — "Debug API by @ArugerDev" — is
greatly appreciated. See COPYRIGHT for the long form.
Copyright © 2026 ArugerDev (@ArugerDev).
Universal, scalable, production-ready debugging system for Godot 4.x.
Drop the addon, enable the plugin, and get 50+ built-in monitors (FPS, memory, GPU, draw calls, physics, scene tree, audio, network, system info, ...) with one line of code:
DebugAPI.enable_monitor_preset("essential")
Or build your own panels with declarative widgets — bind a value to a TextWidget / ProgressWidget / GraphWidget / ConditionalWidget / TimerWidget / VectorWidget and it auto-refreshes. Smart-diff updates and per-widget rate limiting keep the panel under 1 ms/frame even with 50+ widgets active.
FEATURES
• 50+ built-in monitors organised in 12 categories (performance, memory, objects, rendering, physics, audio, display, system, time, input, scene, network)
• 8 named presets (minimal, essential, performance, memory, rendering, system, display, full)
• 7 built-in themes (Default, Dark, Light, Neon, Retro, Minimal, Solarized) + full custom
• 4 install modes: editor plugin (recommended), manual autoload, drop-in DebugBootstrap node, pure instance via preload
• Inspector-driven configuration via a DebugSettings resource
• 8 anchor presets (corners, edges, centre, free) with edge_margin and viewport-aware repositioning
• Optional title bar, collapsible sections, scrollable panels, custom font support, click-through
• Hotkeys via InputMap actions or raw keycodes; global toggle and export shortcuts
• TXT / JSON / CSV export with auto-detection by file extension; auto-export on interval
• Settings persistence: snapshot_settings() + save/load to .tres
• Zero-code config: drop res://debug_settings.tres and the API auto-applies it on _ready
• Headless-safe; runs on Forward+, Mobile and Compatibility renderers
• Multi-language documentation (English, Español, Français, Deutsch, Português) included
• Godot 4.0+ (tested on 4.4.1)
DOCUMENTATION
Full README with step-by-step tutorial, monitor catalogue, widget reference, theme gallery, configuration reference, hotkeys, export guide, performance notes, troubleshooting and complete API reference at the repository.
LICENSE
MIT — free for any use, attribution preserved via the copyright notice.
Reviews
Quick Information
Universal, scalable, production-ready debugging system for Godot 4.x.Drop the addon, enable the plugin, and get 50+ built-in monitors (FPS, memory, GPU, draw calls, physics, scene tree, audio, network, system info, ...) with one line of code: DebugAPI.enable_monitor_preset("essential")Or build your own panels with declarative widgets — bind a value to a TextWidget / ProgressWidget / GraphWidget / ConditionalWidget / TimerWidget / VectorWidget and it auto-refreshes. Smart-diff updates and per-widget rate limiting keep the panel under 1 ms/frame even with 50+ widgets active.FEATURES• 50+ built-in monitors organised in 12 categories (performance, memory, objects, rendering, physics, audio, display, system, time, input, scene, network)• 8 named presets (minimal, essential, performance, memory, rendering, system, display, full)• 7 built-in themes (Default, Dark, Light, Neon, Retro, Minimal, Solarized) + full custom• 4 install modes: editor plugin (recommended), manual autoload, drop-in DebugBootstrap node, pure instance via preload• Inspector-driven configuration via a DebugSettings resource• 8 anchor presets (corners, edges, centre, free) with edge_margin and viewport-aware repositioning• Optional title bar, collapsible sections, scrollable panels, custom font support, click-through• Hotkeys via InputMap actions or raw keycodes; global toggle and export shortcuts• TXT / JSON / CSV export with auto-detection by file extension; auto-export on interval• Settings persistence: snapshot_settings() + save/load to .tres• Zero-code config: drop res://debug_settings.tres and the API auto-applies it on _ready• Headless-safe; runs on Forward+, Mobile and Compatibility renderers• Multi-language documentation (English, Español, Français, Deutsch, Português) included• Godot 4.0+ (tested on 4.4.1)DOCUMENTATIONFull README with step-by-step tutorial, monitor catalogue, widget reference, theme gallery, configuration reference, hotkeys, export guide, performance notes, troubleshooting and complete API reference at the repository.LICENSEMIT — free for any use, attribution preserved via the copyright notice.