godot-nodes-scenes について
Godot 4.7 でシーンを構成し、ノードツリーや実行時インスタンスを安全に管理する開発者向けのスキルです。再利用可能な PackedScene の手順、オートロード、ノードアクセスに加え、参照を調べる Python チェッカーを説明します。
主な機能
- 01シーンとノードの構成
- 02PackedScene の実行時インスタンス化
- 03安全なノードアクセスと解放
- 04オートロード設定の案内
- 05Python によるプロジェクト参照チェッカー
活用シーン
- 01再利用可能なゲーム機能の構成
- 02実行時の弾や敵の生成
- 03欠落または解放済みノードのデバッグ
- 04シーンとリソースの参照確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill godot-nodes-scenesインストール後、Claude Code で/godot-nodes-scenesを入力して読み込まれたか確認します。
同梱ファイルreferences/tree-and-instancing.mdscripts/check_godot_project.py
詳細
Godot のノードとシーン(4.x)
ノードとシーンを組み合わせてゲームを構成し、実行時にインスタンス化し、解放済みまたは見つからないノードでクラッシュすることなくツリーにアクセスします。対象は Godot 4.7 です。
使用する場面
.tscnシーンを構成するとき、機能をどのようにノードに分割するか決めるとき、PackedScene(弾、敵、UI)をインスタンス化するとき、またはオートロードシングルトンを設定するときに使用します。get_node()/$Pathがnullを返す問題や、「Attempt to call on a previously freed instance」のデバッグに使用します。
使用しない場面: GDScript の言語/構文 → godot-gdscript、シグナルベースの疎結合 → godot-signals-groups、物理ボディ/衝突 → godot-physics。
基本的なワークフロー
- コンポジションでモデル化します。 シーンは
.tscnとして保存されるノードツリーです。小さく単一目的のシーン(Player、Bullet、Enemy)を作り、それらを組み合わせて大きなシーンを構成します。深い継承よりも子ノードの追加を優先してください。 - ルートにスクリプトを付けて
@export設定を公開し、シーンを再利用可能にします。 保存すると、何度でもインスタンス化できるPackedSceneになります。 - 実行時にインスタンス化します。
preload/load→scene.instantiate()→add_child(instance)の順に実行します。位置や状態は追加した_後_に設定します(追加前でも、どちらでも構いません)。 - ノードには安全にアクセスします。 固定の子ノードには
@onready var x = $Pathを使用します。ツリーの深い位置にあるノードには一意の名前(%Name)を使用し、ノードがまだ存在すると思い込まないでください。 - グローバルな状態やサービスにはオートロードを使用します(ゲーム状態、オーディオ、シーン切り替えなど)。Project Settings > Globals (Autoload) で登録すると、どこからでも名前でアクセスできます。
- ノードは
queue_free()で解放し、 その後のアクセスはis_instance_valid()で保護します。 - 完了前に参照を確認します。 シーン、リソース、スクリプトを作成、移動、または名前変更した後、
python scripts/check_godot_project.py <project-dir>を実行します(Godot のインストールは不要です。機械可読な出力には--jsonを使用します)。すべてのERROR(存在しない、または大文字小文字が誤っているres://パス、宣言されていないExtResource/SubResourceID、不正なparent=パス、メインシーンまたはオートロードの欠落)を修正し、終了コードが 0 になるまで再実行してください。Godot が uid から見つけられる古いpath=などの警告は問題ありませんが、修正する価値があります。このスクリプトはこのスキルディレクトリからの相対パスで実行するか、先にインストール済みのスキルパスを解決してください。必要なのは Python 3.10+ のみで、ほかに依存関係はありません。また、Godot でプロジェクトを開く作業の代わりにはなりません。
パターン
1. 実行時にシーンをインスタンス化する
extends Node2D
const BULLET := preload("res://bullet.tscn") # preload: loaded at compile time
func shoot(at: Vector2, dir: Vector2) -> void:
var bullet := BULLET.instantiate() # create an instance of the scene
bullet.global_position = at
bullet.direction = dir # set exported/public state
add_child(bullet) # now it's in the tree and runs
2. 安全なノードアクセス:$, get_node_or_null、一意の名前
@onready var label: Label = $UI/Label # $ is sugar for get_node("UI/Label")
@onready var health_bar: ProgressBar = %HealthBar # % = scene-unique name (rename-proof)
func update() -> void:
var optional := get_node_or_null("Maybe/Missing") # returns null instead of erroring
if optional:
optional.queue_free()
3. オートロードシングルトン(グローバルなゲーム状態)
# game_state.gd — add in Project Settings > Globals > Autoload as "GameState".
extends Node
var score := 0
signal score_changed(value: int)
func add_score(points: int) -> void:
score += points
score_changed.emit(score) # any scene can: GameState.score_changed.connect(...)
4. 実行中のシーンを変更する
func go_to_level_2() -> void:
# Swaps the current scene for another. Frees the old scene tree.
get_tree().change_scene_to_file("res://levels/level_2.tscn")
# Or, with a preloaded PackedScene:
# get_tree().change_scene_to_packed(LEVEL_2)
注意点
$Path/get_node()がnullを返す、またはエラーになる場合: パスが間違っているか、ノードがまだツリーに入っていません。@onreadyを使用し、パスがシーンと一致することを確認するか、任意のノードにはget_node_or_null()を使用してください。- ノードの名前を変更すると
$Pathが壊れます。 深い階層への参照を名前変更や親の変更後も維持するには、一意の名前(%Name。右クリック > Access as Unique Name で設定)を使用してください。 - フレームの途中で
free()を呼び出すと、 そのノードをまだ使用しているほかのコードがクラッシュすることがあります。queue_free()(フレームの終わりに削除)を優先し、is_instance_valid(node)を確認してください。 add_child()の前に子ノードの状態を設定しても問題ありませんが、 子ノードの_ready()が実行されるのはツリーに入った_後_です。その前に@onready変数を使えると思い込まないでください。- オートロードの順序は重要です。 オートロードはメインシーンより前に、リストの順番で追加されます。オートロードは、まだ存在していないメインシーンに依存できません。
instance()は Godot 4 でinstantiate()に名前が変更されました。preloadは解析時に実行されるため、パスは定数でなければなりません。loadは実行時に実行されるため、パスに変数を使用できます。change_scene_to_file()は即時ではなく遅延実行されます。 Godot は現在のフレームの終わりにシーンを切り替え、古いシーンを解放します。呼び出し後のコードは引き続き_古い_ツリーに対して実行され、get_tree().current_sceneが新しいシーンになるのは次のフレームです。同じ行で新しいシーンのノードを読み取らないでください。新しいシーンの_ready()から読み取ります。
参考資料
- シーンの継承、コードからシーンを保存する際の
owner/所有権、グループと一意名の違い、ノードパスのエッジケースについては、references/tree-and-instancing.mdをお読みください。 scripts/check_godot_project.py— Godot 4.x プロジェクト用の読み取り専用リファレンスチェッカーです。--helpで、すべてのチェック項目と終了コードを確認できます。
関連スキル
godot-gdscript— 言語、ライフサイクル、@onreadyについて説明します。godot-signals-groups— インスタンス化されたシーンを、その生成元から切り離します。godot-resources— データを複製せずに、インスタンス間で共有します。save-systems— 実行をまたいでシーン/ゲームの状態を保持します。
コメント
Markdown 対応