mcpField
G
godot-debugging

godot-debugging

github.com/jame581開発901197 回インストール1 週間前に更新
リポジトリ

godot-debugging について

GDScript または C# を使う Godot 4.3+ プロジェクト向けの体系的なデバッグスキルです。ログ、ブレークポイント、シグナル、シーンの確認、プロファイリングと、修正を検証する手順を扱います。

主な機能

  1. 01ログとブレークポイントで実行状態を確認
  2. 02シグナル接続と実行中のノードを確認
  3. 03組み込みプロファイラーでボトルネックを特定
  4. 04よくあるエラーと原因を把握
  5. 05手順に沿って問題を再現・修正・検証

活用シーン

  1. 01ノードパスや null インスタンスのエラーを調査
  2. 02重複または未接続のシグナルを追跡
  3. 03関数の遅延やメモリ増加を特定
  4. 04バグ修正後に回帰テストを追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jame581/godotprompter --skill godot-debugging

インストール後、Claude Code で/godot-debuggingを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
performance-debugging.md
scene-tree-debugging.md
signal-tracing.md
systematic-method.md

詳細

Godot のデバッグ

このスキルでは、GDScript と C# の両方を対象に、Godot 4.3 以降のプロジェクトを体系的にデバッグする方法を説明します。print を使ったテクニック、ブレークポイント、シグナルの追跡、組み込みプロファイラー、シーンツリーの検査、よくあるエラーパターン、手順に沿ったデバッグチェックリストを扱います。

関連スキル: パフォーマンスのプロファイリングについては godot-optimization、修正後の回帰テストについては godot-testing、C# のシグナルのデバッグパターンについては csharp-signals を参照してください。


1. print によるデバッグ

GDScript

Godot には、用途の異なる複数の print 関数が用意されています。ログの重要度と状況に応じて選択してください。

# print() — general output, space-separated values
print("Player position: ", position)
print("Health: ", health, " / ", max_health)

# print_rich() — BBCode-formatted output in the Output panel
print_rich("[color=yellow]WARNING:[/color] Enemy count exceeded limit: ", enemy_count)
print_rich("[b]State:[/b] [color=green]", current_state, "[/color]")

# push_error() — logs an error with a full stack trace; does NOT stop execution
push_error("save_game: file path is empty")

# push_warning() — logs a warning with stack trace; use for recoverable issues
push_warning("AudioStreamPlayer: bus '%s' not found, using Master" % bus_name)

# print_debug() — print() plus the calling file:line when the debugger is attached;
# it still prints in release exports (guard with OS.is_debug_build() to silence it)
print_debug("Frame delta: ", delta, " | FPS: ", Engine.get_frames_per_second())

# printerr() — prints to stderr; visible in external terminals and CI logs
printerr("Critical: physics state corrupted at frame ", Engine.get_process_frames())

書式付き出力のパターン:

# String formatting with % operator
print("Actor [%s] dealt %d damage to [%s]" % [name, damage, target.name])

# String.format() with named placeholders
var msg := "Position: ({x}, {y}) at speed {spd}"
print(msg.format({"x": position.x, "y": position.y, "spd": velocity.length()}))

# Printing arrays and dictionaries — use str() for clean output
var inventory := {"sword": 1, "potion": 3}
print("Inventory: ", str(inventory))

# Conditional verbose logging using a project-level constant or autoload flag
if DebugConfig.verbose_ai:
    print_rich("[color=cyan][AI][/color] ", agent.name, " chose action: ", chosen_action)
// String interpolation
GD.Print($"Actor [{Name}] dealt {damage} damage to [{target.Name}]");

// Printing collections
var inventory = new Godot.Collections.Dictionary { { "sword", 1 }, { "potion", 3 } };
GD.Print("Inventory: ", inventory);

// Conditional verbose logging
if (DebugConfig.VerboseAi)
    GD.PrintRich($"[color=cyan][AI][/color] {agent.Name} chose action: {chosenAction}");

各関数の用途:

関数リリースビルドで表示スタックトレース用途
print()はい(削除されていない場合)いいえ一般的な値の確認
print_rich()はいいいえカテゴリ分けされた色付きログ
push_error()はいはい無効な状態、プログラマーエラー
push_warning()はいはい回復可能な問題
print_debug()はい呼び出し行(デバッガー接続時)値が出力された場所の特定
printerr()はいいいえ外部ターミナル/CI の出力
C#
using Godot;

public partial class Player : CharacterBody3D
{
    public override void _Ready()
    {
        // GD.Print — equivalent to GDScript print()
        GD.Print("Player position: ", Position);

        // GD.PrintRich — BBCode formatted
        GD.PrintRich("[color=yellow]Ready called on[/color] ", Name);

        // GD.PushError — logs error with stack trace
        GD.PushError("_Ready: required child node missing");

        // GD.PushWarning — logs warning with stack trace
        GD.PushWarning("AudioBus not found, falling back to Master");

        // GD.PrintErr — writes to stderr
        GD.PrintErr("Critical failure in _Ready");
    }

    private void HandleDamage(int amount)
    {
        // Formatted string output
        GD.Print($"[{Name}] took {amount} damage. HP: {_health}/{_maxHealth}");
    }
}

2. ブレークポイントとリモートデバッガー

ブレークポイントの設定
  • スクリプトエディターで行番号の左側にある余白をクリックすると、ブレークポイントを切り替えられます。赤い点が表示されます。
  • F9 を押すと、現在の行のブレークポイントを切り替えられます。
  • GDScript で breakpoint をステートメントとして使うと、プログラムからブレークポイントを発生させられます。
func _physics_process(delta: float) -> void:
    if velocity.length() > MAX_SPEED:
        breakpoint  # execution pauses here during debug runs
    move_and_slide()
  • C# では、System.Diagnostics.Debugger.Break() を使うか、.NET デバッガー(JetBrains Rider、または Godot 拡張機能を使った VS Code など)をアタッチしてください。
public override void _PhysicsProcess(double delta)
{
    if (Velocity.Length() > MaxSpeed)
    {
        System.Diagnostics.Debugger.Break(); // pause if .NET debugger is attached
    }
    MoveAndSlide();
}
組み込みデバッガーパネルの使用

ブレークポイントで実行が一時停止すると、エディター下部の Debugger パネルで次の操作を行えます。

  • スタックフレーム — 完全な呼び出しスタックを表示します。フレームをクリックすると、そのローカル変数を調べられます。
  • ローカル/メンバー/グローバル — 変数の値を実行中に確認・変更できます。
  • ステップイン(F11)/ステップオーバー(F10) — 行ごとに実行を進めます(Godot 4.6 では ステップアウト、Alt+F11 も使用できます)。
  • 続行(F12) — 次のブレークポイントまで実行を再開します。
リモートシーンインスペクター

実行中のゲームが一時停止中、またはセッションの途中であるときは、次の手順を実行します。

  1. エディターで Debugger > Remote タブを開きます。
  2. シーンパネル(左上の「Scene」の横にある切り替えボタン)で Remote をクリックし、シーンツリーを実行中の表示に切り替えます。
  3. 実行中のノードをクリックすると、インスペクターで現在のプロパティを確認できます。
  4. ここで変更したプロパティは、テスト用にすぐに反映されます。
Monitors タブ

Debugger > Monitors では、エンジンのメトリクスをリアルタイムで表示できます。

  • FPS/処理時間/物理演算時間 — パフォーマンスの低下を検出します。
  • ビデオ RAM/オブジェクト数/ノード数 — メモリの増加を追跡します。
  • 物理演算 2D/3D の衝突ペア数 — 処理負荷の高い物理シーンを特定します。
  • オーディオレイテンシ — オーディオコールバックのオーバーランを検出します。

モニター名をクリックすると、そのグラフが開きます。Add ボタンを使うと、カスタムのモニターダッシュボードを作成できます。


3. シグナルのデバッグ

実行時に node.get_signal_connection_list("signal_name") で確認できます(callable、flags、signal を含む Dictionary の Array を返します)。よくあるシグナルの不具合は、接続を二重に行うこと(ハンドラーが 2 回呼び出される)、解放時に切断し忘れること(警告とダングリング参照が発生する)、ハンドラーのシグネチャが誤っていること(emit のたびに Error calling from signal … が発生する)です。

GDScript と C# の完全な検査ヘルパー、およびよくあるシグナルの問題の一覧(重複接続、deferred-free の競合、ラムダキャプチャのライフサイクル、signal と Callable の使い分け)については、references/signal-tracing.md を参照してください。


4. よくあるエラーパターン

エラーメッセージ原因修正方法
Node not found: "Player" (relative to "...")ノードパスが間違っている、ノード名が変更された、またはツリーに追加される前にアクセスしている_ready() 内または呼び出し後にのみ $NodeName を使用します。print(get_node_or_null("Player")) でパスを確認します。@onready を使用します。
Attempt to call function on a null instanceノードが解放された、エクスポート変数が割り当てられていない、または get_node() が null を返したis_instance_valid(node) でチェックします。インスペクターでエクスポート変数を確認します。@onready var _node := $Node を優先して使用します。
Can't change this state while flushing queriesbody_entered などの物理コールバック内で、CollisionShape を無効にするなど、物理状態を変更している変更を遅延させます:collision_shape.set_deferred("disabled", true)。
Invalid call. Nonexistent function 'X' in base 'Y'その型に存在しないメソッドを呼び出している、またはノードに誤った型としてアクセスしているclass_name を確認し、as でキャストするか、スクリプトがアタッチされていることを確認します。ガードには has_method("X") を使用します。
Converting circular structure to JSON. / Circular reference to resource being saved foundResource または Dictionary が直接または間接的に自身を参照している循環参照を解消します。可能な場合はリソース参照の代わりにノード参照を使用するか、サブリソースをローカル専用としてマークします。
Cannot call non-static function "x()" from the static function "y()".static func からインスタンスメソッドを呼び出している呼び出しをインスタンスのコンテキストに移すか、引数としてデータを受け取る適切な静的ヘルパーにリファクタリングします。
Stack overflow. Check for infinite recursion in your script.無限再帰です。多くの場合、シグナルが自身を再度トリガーしているか、セッターが自身を設定していますセッターにガード変数(_updating := true)を追加します。デバッガーでコールスタックを追跡します。
Signal 'x' is already connected to given callable '…' in that object.CONNECT_REFERENCE_COUNTED を指定せずに、同じシグナルと呼び出し可能オブジェクトの組み合わせに対して connect() を二度目に呼び出している接続前に is_connected() を確認するか、先に切断するか、CONNECT_REFERENCE_COUNTED を使用します。
Out of bounds get index 'X' (on base: 'Array')Array または PackedArray の長さを超える位置にアクセスしているアクセス前にインデックスを検証します:if index < array.size()。利用可能な場合は array.get(index) を使用します。
音声にノイズが入る、または途切れる(アンダーラン)音声コールバックが期限に間に合わない。音声スレッドで処理しすぎているオーディオバスのエフェクトを減らす、ポリフォニーを下げる、またはプロジェクト設定でオーディオバッファーサイズを大きくします。

5. パフォーマンスのデバッグ

プロファイラー(デバッガー → プロファイラー)には、関数ごとの自己実行時間と呼び出し回数が表示されます。モニタータブでは、フレーム時間、FPS、ドローコール数、物理ティックの予算、メモリを追跡できます。最も負荷の高いゲームプレイシナリオで両方を開き、プロファイラーを自己実行時間で並べ替えて、ボトルネックの原因を見つけます。ドローコールのボトルネックを調べるには、モニタータブの Raster > Total Draw Calls を確認します。

プロファイラーのワークフロー、モニタータブの使用方法、ドローコールのボトルネックの特定、物理ティックの監視パターンについては、references/performance-debugging.md を参照してください。ボトルネックを特定した後の修正方法については、godot-optimization も参照してください。


6. シーンツリーのデバッグ

print_tree_pretty() は現在のシーンツリーを標準出力にダンプします。ノードが想定した場所にあることを確認する最も手早い方法です。エディターの リモート タブには、ゲームの実行中にライブのシーンツリーが表示されます。@tool ノードでは、_get_configuration_warnings() を実装して、エディターの SceneTree ドックに設定エラーを表示します。

詳しい例(print_tree_pretty のパターン、ノードグループのデバッグヘルパー、_get_configuration_warnings の GDScript と C#)については、references/scene-tree-debugging.md を参照してください。


7. 系統的なデバッグ手法

プリント出力、ブレークポイント、リモートでの調査ですぐにバグが見つからない場合は、意識的なプロセスに切り替えます。再現 → 切り分け → 仮説 → トレース → 修正 → 検証 → テストの追加の順で進めます。各ステップを完了してから次へ進みます。先に進みすぎると時間を無駄にします。

各ステップの具体的な手法(二分探索、最小再現、回帰テストのパターン)を含む7ステップの手法については、references/systematic-method.md を参照してください。


8. 実装チェックリスト

  • 詳細なフレーム単位の出力は OS.is_debug_build() で保護してください。print() も print_debug() もリリースビルドでは削除されません。
  • 無効な状態や回復可能な問題には、print() ではなく push_error() / push_warning() を使用してください。これらにはスタックトレースが含まれます。
  • プリント出力をあちこちに追加する代わりに、F9 または breakpoint 文でブレークポイントを設定して実行を一時停止してください。
  • シグナルが正しく接続されていると思い込まず、get_signal_connection_list() でシグナルの接続を確認してください。
  • デバッグセッション中に Scene → Remote を開いてライブのシーンツリーを調べ、実行時のノード状態を確認してください。
  • 最適化の前に Debugger → Profiler を開いて Self 時間を測定し、まず実際のボトルネックを特定してください。
  • Debugger → Monitors で Object Count または Video RAM が増加していないか確認し、メモリーリークの兆候を調べてください。
  • 待機中にノードが解放された場合に備え、await の後に実行されるコードでは is_instance_valid() を使用してください。
  • 再現 → 切り分け → 仮説 → トレース → 修正 → 検証 → テストの順に従ってください。修正に先走らないでください。
  • バグを修正したら、同じ不具合が気づかないうちに再発しないよう、名前付きの回帰テストを作成してください。

コメント