godot-debugging-profiling

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Debugging & Profiling

调试与性能分析

Expert guidance for finding and fixing bugs efficiently with Godot's debugging tools.
使用Godot调试工具高效查找和修复bug的专业指南。

NEVER Do

绝对不要做的事

  • NEVER use
    print()
    without descriptive context
    print(value)
    is useless. Use
    print("Player health:", health)
    with labels.
  • NEVER leave debug prints in release builds — Wrap in
    if OS.is_debug_build()
    or use custom DEBUG const. Prints slow down release.
  • NEVER ignore
    push_warning()
    messages
    — Warnings indicate potential bugs (null refs, deprecated APIs). Fix them before they become errors.
  • NEVER use
    assert()
    for runtime validation in release
    — Asserts are disabled in release builds. Use
    if not condition: push_error()
    for runtime checks.
  • NEVER profile in debug mode — Debug builds are 5-10x slower. Always profile with release exports or
    --release
    flag.

  • 绝对不要在没有描述性上下文的情况下使用
    print()
    print(value)
    毫无用处。要使用带标签的写法,比如
    print("Player health:", health)
  • 绝对不要在发布版本中保留调试打印代码 — 要将其包裹在
    if OS.is_debug_build()
    中,或使用自定义DEBUG常量。打印操作会拖慢发布版本的运行速度。
  • 绝对不要忽略
    push_warning()
    消息
    — 警告预示着潜在的bug(空引用、已弃用的API等)。在它们演变为错误之前就修复掉。
  • 绝对不要在发布版本中使用
    assert()
    进行运行时验证
    — 断言在发布版本中会被禁用。运行时检查请使用
    if not condition: push_error()
  • 绝对不要在调试模式下进行性能分析 — 调试版本的运行速度比发布版本慢5-10倍。请始终使用发布导出版本或
    --release
    标志进行性能分析。

Available Scripts

可用脚本

MANDATORY: Read the appropriate script before implementing the corresponding pattern.
强制要求:在实现对应模式前,请先阅读相应的脚本。

performance_plotter.gd

performance_plotter.gd

Custom Performance monitors for gameplay metrics (projectile/enemy count). Includes automated error state capture with stack traces and memory stats.
用于游戏玩法指标(投射物/敌人数量)的自定义性能监控器。包含自动捕获错误状态的功能,同时记录堆栈跟踪和内存统计数据。

debug_overlay.gd

debug_overlay.gd

In-game debug UI with real-time FPS, memory, orphan nodes, and custom metrics.
Do NOT Load debug_overlay.gd in release builds - wrap usage in
if OS.is_debug_build()
.

游戏内调试UI,可实时显示FPS、内存、孤立节点以及自定义指标。
请勿在发布版本中加载 debug_overlay.gd - 要将其使用逻辑包裹在
if OS.is_debug_build()
中。

Print Debugging

打印调试

gdscript
undefined
gdscript
undefined

Basic print

Basic print

print("Value: ", some_value)
print("Value: ", some_value)

Formatted print

Formatted print

print("Player at %s with health %d" % [position, health])
print("Player at %s with health %d" % [position, health])

Print with caller info

Print with caller info

print_debug("Debug info here")
print_debug("Debug info here")

Warning (non-fatal)

Warning (non-fatal)

push_warning("This might be a problem")
push_warning("This might be a problem")

Error (non-fatal)

Error (non-fatal)

push_error("Something went wrong!")
push_error("Something went wrong!")

Assert (fatal in debug)

Assert (fatal in debug)

assert(health > 0, "Health cannot be negative!")
undefined
assert(health > 0, "Health cannot be negative!")
undefined

Breakpoints

断点

Set Breakpoint:
  • Click line number gutter in script editor
  • Or use
    breakpoint
    keyword:
gdscript
func suspicious_function() -> void:
    breakpoint  # Execution stops here
    var result := calculate_something()
设置断点:
  • 点击脚本编辑器中的行号 gutter 区域
  • 或使用
    breakpoint
    关键字:
gdscript
func suspicious_function() -> void:
    breakpoint  # Execution stops here
    var result := calculate_something()

Debugger Panel

调试器面板

Debug → Debugger (Ctrl+Shift+D)
Tabs:
  • Stack Trace: Call stack when paused
  • Variables: Inspect local/member variables
  • Breakpoints: Manage all breakpoints
  • Errors: Runtime errors and warnings
调试 → 调试器(Ctrl+Shift+D)
标签页:
  • 堆栈跟踪:暂停时的调用堆栈
  • 变量:检查局部/成员变量
  • 断点:管理所有断点
  • 错误:运行时错误与警告

Remote Debug

远程调试

Debug running game:
  1. Run project (F5)
  2. Debug → Remote Debug → Select running instance
  3. Inspect live game state
调试运行中的游戏:
  1. 运行项目(F5)
  2. 调试 → 远程调试 → 选择运行中的实例
  3. 检查实时游戏状态

Common Debugging Patterns

常见调试模式

Null Reference

空引用

gdscript
undefined
gdscript
undefined

❌ Crash: null reference

❌ Crash: null reference

$NonExistentNode.do_thing()
$NonExistentNode.do_thing()

✅ Safe: check first

✅ Safe: check first

var node := get_node_or_null("MaybeExists") if node: node.do_thing()
undefined
var node := get_node_or_null("MaybeExists") if node: node.do_thing()
undefined

Track State Changes

跟踪状态变化

gdscript
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 = value
gdscript
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 = value

Visualize Raycasts

可视化射线检测

gdscript
func _draw() -> void:
    if Engine.is_editor_hint():
        draw_line(Vector2.ZERO, ray_direction * ray_length, Color.RED, 2.0)
gdscript
func _draw() -> void:
    if Engine.is_editor_hint():
        draw_line(Vector2.ZERO, ray_direction * ray_length, Color.RED, 2.0)

Debug Draw in 3D

3D调试绘制

gdscript
undefined
gdscript
undefined

Use DebugDraw addon or create debug meshes

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)
undefined
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)
undefined

Error Handling

错误处理

gdscript
undefined
gdscript
undefined

Handle file errors

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
undefined
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
undefined

Profiler

性能分析器

Debug → Profiler (F3)
调试 → 性能分析器(F3)

Time Profiler

时间分析器

  • Shows function execution times
  • Identify slow functions
  • Target: < 16.67ms per frame (60 FPS)
  • 显示函数执行时间
  • 识别缓慢的函数
  • 目标:每帧耗时 < 16.67ms(60 FPS)

Monitor

监控面板

  • FPS, physics, memory
  • Object count
  • Draw calls
  • FPS、物理运算、内存
  • 对象数量
  • 绘制调用次数

Common Performance Issues

常见性能问题

Issue: Low FPS

问题:低FPS

gdscript
undefined
gdscript
undefined

Check in _process

Check in _process

func _process(delta: float) -> void: print(Engine.get_frames_per_second()) # Monitor FPS
undefined
func _process(delta: float) -> void: print(Engine.get_frames_per_second()) # Monitor FPS
undefined

Issue: Memory Leaks

问题:内存泄漏

gdscript
undefined
gdscript
undefined

Check with print

Check with print

func _exit_tree() -> void: print("Node freed: ", name)
func _exit_tree() -> void: print("Node freed: ", name)

Use groups to track

Use groups to track

add_to_group("tracked") print("Active objects: ", get_tree().get_nodes_in_group("tracked").size())
undefined
add_to_group("tracked") print("Active objects: ", get_tree().get_nodes_in_group("tracked").size())
undefined

Issue: Orphaned Nodes

问题:孤立节点

gdscript
undefined
gdscript
undefined

Check for orphans

Check for orphans

func check_orphans() -> void: print("Orphan nodes: ", Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT))
undefined
func check_orphans() -> void: print("Orphan nodes: ", Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT))
undefined

Debug Console

调试控制台

gdscript
undefined
gdscript
undefined

Runtime debug console

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_visible
undefined
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_visible
undefined

Best Practices

最佳实践

1. Use Debug Flags

1. 使用调试标志

gdscript
const DEBUG := true

func debug_log(message: String) -> void:
    if DEBUG:
        print("[DEBUG] ", message)
gdscript
const DEBUG := true

func debug_log(message: String) -> void:
    if DEBUG:
        print("[DEBUG] ", message)

2. Conditional Breakpoints

2. 条件断点

gdscript
undefined
gdscript
undefined

Only break on specific condition

Only break on specific condition

if player.health <= 0: breakpoint
undefined
if player.health <= 0: breakpoint
undefined

3. Scene Tree Inspector

3. 场景树检查器

Debug → Remote Debug → Inspect scene tree
See live node hierarchy
Debug → Remote Debug → Inspect scene tree
See live node hierarchy

Reference

参考资料

Related

相关内容

  • Master Skill: godot-master
  • 核心技能:godot-master