Loading...
Loading...
Expert debugging workflows including print debugging (push_warning, push_error, assert), breakpoints (conditional breakpoints), Godot Debugger (stack trace, variables, remote debug), profiler (time profiler, memory monitor), error handling patterns, and performance optimization. Use for bug fixing, performance tuning, or development diagnostics. Trigger keywords: breakpoint, print_debug, push_error, assert, profiler, remote_debug, memory_leak, orphan_nodes, Performance.get_monitor.
npx skill4agent add thedivergentai/gd-agentic-skills godot-debugging-profilingprint()print(value)print("Player health:", health)if OS.is_debug_build()push_warning()assert()if not condition: push_error()--releaseMANDATORY: Read the appropriate script before implementing the corresponding pattern.
Do NOT Load debug_overlay.gd in release builds - wrap usage in.if OS.is_debug_build()
# Basic print
print("Value: ", some_value)
# Formatted print
print("Player at %s with health %d" % [position, health])
# Print with caller info
print_debug("Debug info here")
# Warning (non-fatal)
push_warning("This might be a problem")
# Error (non-fatal)
push_error("Something went wrong!")
# Assert (fatal in debug)
assert(health > 0, "Health cannot be negative!")breakpointfunc suspicious_function() -> void:
breakpoint # Execution stops here
var result := calculate_something()# ❌ Crash: null reference
$NonExistentNode.do_thing()
# ✅ Safe: check first
var node := get_node_or_null("MaybeExists")
if node:
node.do_thing()var _health: int = 100
var health: int:
get:
return _health
set(value):
print("Health changed: %d → %d" % [_health, value])
print_stack() # Show who changed it
_health = valuefunc _draw() -> void:
if Engine.is_editor_hint():
draw_line(Vector2.ZERO, ray_direction * ray_length, Color.RED, 2.0)# Use DebugDraw addon or create debug meshes
func debug_draw_sphere(pos: Vector3, radius: float) -> void:
var mesh := SphereMesh.new()
mesh.radius = radius
var instance := MeshInstance3D.new()
instance.mesh = mesh
instance.global_position = pos
add_child(instance)# Handle file errors
func load_save() -> Dictionary:
if not FileAccess.file_exists(SAVE_PATH):
push_warning("No save file found")
return {}
var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
if file == null:
push_error("Failed to open save: %s" % FileAccess.get_open_error())
return {}
var json := JSON.new()
var error := json.parse(file.get_as_text())
if error != OK:
push_error("JSON parse error: %s" % json.get_error_message())
return {}
return json.data# Check in _process
func _process(delta: float) -> void:
print(Engine.get_frames_per_second()) # Monitor FPS# Check with print
func _exit_tree() -> void:
print("Node freed: ", name)
# Use groups to track
add_to_group("tracked")
print("Active objects: ", get_tree().get_nodes_in_group("tracked").size())# Check for orphans
func check_orphans() -> void:
print("Orphan nodes: ", Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT))# Runtime debug console
var console_visible := false
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.keycode == KEY_QUOTELEFT:
console_visible = not console_visible
$DebugConsole.visible = console_visibleconst DEBUG := true
func debug_log(message: String) -> void:
if DEBUG:
print("[DEBUG] ", message)# Only break on specific condition
if player.health <= 0:
breakpointDebug → Remote Debug → Inspect scene tree
See live node hierarchy