概要
Godot Engineでゲーム制作を始めるにあたり、誰もが最初に学ぶべき最も重要な概念が「シーン (Scene)」と「ノード (Node)」です。ひとことで言えば、 ノードは「部品」、シーンは部品を組み立てた「設計図」 ——この2つの関係性を理解することが、Godotを使いこなすための鍵になります。
この記事でわかること
- ノード ——ゲームを構成する最小単位の「部品」
- シーン ——ノードをツリー状に組み立てた「設計図」(
.tscnファイル)- インスタンス化 ——シーンを別のシーンの部品として使い回す仕組み
@onready・シグナルなど、 よくある間違いを避けるベストプラクティス
ノードとは? - ゲームを構成する「部品」
ノードは、Godotにおけるゲームの基本的な構成要素、つまり「部品」です。それぞれのノードは、特定の機能を持っています。
- Sprite2D: 画像を表示する
- AudioStreamPlayer: 音を再生する
- CollisionShape2D: 物理的な衝突範囲(当たり判定)を定義する
- Button: クリック可能なUIボタン
- Camera2D: 2Dゲーム内のカメラ

これらはごく一部であり、Godotには何百もの特殊なノードが用意されています。1つのノードは1つの仕事しかしません。だからこそ、これらの「部品」を自由に組み合わせることで、ゲーム内のあらゆるオブジェクトやシステムを構築できるのです。
シーンとは? - 部品を組み立てた「設計図」
シーンは、これらのノードを 階層的なツリー構造 で組み合わせたものです。1つの「ルートノード」と、それに連なる複数の「子ノード」で構成されます。このノードの集合体が「シーン」であり、ゲーム内のキャラクター、ステージ、UI画面といった、あらゆる要素を表現します。
具体例:2Dゲームの「プレイヤー」シーン
例えば、「プレイヤー」というシーンを作る場合、以下のようなノードの組み合わせが考えられます。
CharacterBody2D (ルートノード: 物理挙動と移動を管理)
├── Sprite2D (子ノード: プレイヤーの見た目を表示)
├── CollisionShape2D (子ノード: 当たり判定の形状を定義)
└── Camera2D (子ノード: プレイヤーを追従するカメラ)

このように、複数のノード(部品)を組み合わせて一つのまとまりにしたものが「シーン」です。 「見た目」「当たり判定」「カメラ」と、1ノード1役の部品を足していくだけ で、キャラクターとして必要な機能が揃っていくのがわかります。作成したシーンは、.tscnという拡張子のファイルとして保存されます。
シーンのインスタンス化 - シーンを「入れ子」にする
Godotの真価は、作成したシーンを、別のシーンの部品(ノード)として再利用できる 「シーンのインスタンス化」 にあります。これは、単なるコピー&ペーストではなく、元のシーン(設計図)への参照を維持する機能です。
具体例:「ステージ」シーンに「プレイヤー」を配置する
先ほど作成した「プレイヤー」シーン(player.tscn)を、「ステージ1」という別のシーンに配置してみましょう。
Node2D (ステージ1のルート)
├── TileMap (地形や背景)
├── Player (player.tscnをインスタンス化)
├── Enemy1 (enemy.tscnをインスタンス化)
└── Enemy2 (enemy.tscnをインスタンス化)
インスタンス化のメリット
- 再利用性: 一度作った「プレイヤー」シーンを、「ステージ2」「ボス戦」など、様々な場所で簡単に使い回せます。
- 保守性: プレイヤーの移動速度を変更したい場合、
player.tscnを一度編集するだけで、全てのプレイヤーインスタンスに修正が反映されます。 - カプセル化: 「ステージ1」シーンは、プレイヤーがどのようなノードで構成されているかという内部構造を意識する必要がありません。

実際のゲーム開発では、この仕組みが「物量」を支えます。シューティングの弾1発、RPGの村人1人、タワーディフェンスの敵1体——ジャンルを問わず、 「シーンを1つ作って、必要なだけインスタンス化する」 が基本形です。弾の当たり判定を直したければbullet.tscnを1回直すだけで、画面上の全弾に反映されます。
よくある間違いとベストプラクティス
| よくある間違い | ベストプラクティス |
|---|---|
| 巨大なモノリシックシーン | 小さな専門シーンに分割する。プレイヤー、敵、弾、UI要素など、再利用可能な単位で積極的にシーン化し、それらを組み合わせて大きなシーンを構築します。 |
| 脆弱なノードパスへの依存 | シグナルとメソッド呼び出しで疎結合を保つ。get_node('../../Player/Camera2D')のような構造に依存したパスは、変更に非常に弱いです(シグナルの記事参照)。 |
_processでの過剰なポーリング | イベント駆動を意識する。入力は_input()や_unhandled_input()で、物理的な衝突はボディのシグナルで検知するなど、必要な時にだけコードが実行されるようにします。 |
get_node()の多用 | @onreadyでノード参照をキャッシュする。_ready関数が呼ばれる前にノード参照を保持しておくことで、コードをクリーンに保ちます。 |
パフォーマンスを意識したシーン設計
プロジェクトが大規模になるにつれて、パフォーマンスは無視できない問題になります。
- ノード数: シーン内のノード、特に毎フレーム処理を行うノードの数は、CPU負荷に直結します。
get_node()の呼び出しコスト:_processのようなループ内でget_node()を呼び出すのは避けるべきです。@onreadyはこの問題を解決するための最もシンプルな解決策です。- 物理演算のコスト: 当たり判定が必要ない装飾的なオブジェクトにまで物理ボディを適用しないように注意しましょう。
実践:敵 を次々に出す「スポナー」を組む
シューティングの敵編隊、タワーディフェンスの侵攻ウェーブ、Vampire Survivors系の湧き——「同じ敵を、時間とともに何体も出す」仕組みは、ジャンルを問わず enemy.tscnを1つ作って、必要なだけインスタンス化する で実現できます。ここまでの「シーン=設計図」「インスタンス化=使い回し」を、ひとつのスポナーに落とし込んでみましょう。

スポナーはTimerノードで一定間隔ごとに敵を1体ずつ生成します。ノード構成はごくシンプルです。
- EnemySpawner (Node2D)
- SpawnTimer (Timer)
extends Node2D
const ENEMY_SCENE = preload("res://enemy.tscn")
@onready var spawn_timer: Timer = $SpawnTimer
func _ready() -> void:
# SpawnTimerのwait_timeはInspectorで設定(例: 1.5秒)
spawn_timer.timeout.connect(_on_spawn_timer_timeout)
spawn_timer.start()
func _on_spawn_timer_timeout() -> void:
var enemy := ENEMY_SCENE.instantiate()
# 敵はスポナーの子ではなく、現在のシーン直下に追加する
get_tree().current_scene.add_child(enemy)
# 画面上端のランダムなX位置から出現させる
enemy.global_position = Vector2(randf_range(0, 1152), -50)
ポイントは2つです。
- 生成した敵は、スポナーの子にしない :
get_tree().current_scene.add_child()で現在のシーン直下に置きます。もしスポナーの子にすると、ステージ遷移などでスポナーが消えた瞬間、湧いた敵まで道連れで消えてしまいます。 - 敵の強さや見た目は
enemy.tscn側で一括管理 :スポナーは「いつ・どこに出すか」だけを担当します。敵のHPやスプライトを変えたくなったらenemy.tscnを1回直すだけで、湧いてくる全部の敵に反映される——これがインスタンス化のうれしさそのものです。
「ウェーブごとに敵の種類を変えたい」「時間で出現数を増やしたい」と欲が出てきたら、スポナーに配列やカウンタを足していきます。敵一体一体の賢い動きは、ステートマシンで管理するAIとプレイヤーの状態の領域です。
まとめ
- ノード: ゲームを構成する最小単位の「部品」。それぞれが特定の機能を持つ
- シーン: ノードをツリー状に組み立てた「設計図」。キャラクターやステージなど、ゲームの具体的な要素を構成する
- インスタンス化: 作成したシーンを、別のシーンの「部品」として再利用すること
Godotでのゲーム開発は、「ノード」を組み合わせて「シーン」を作り、さらにその「シーン」を組み合わせてより大きな「シーン(ゲーム全体)」を構築していく、という流れになります。
次のステップとしては、シーン同士・ノード同士を疎結合につなぐ シグナル と、シーンをまたいでデータを持ち運ぶ Autoload を押さえると、小さなゲームを一本組み立てられるようになります。
補足: Unity経験者向け——同じ「シーン」という名前の罠
UnityからGodotに来た人が最初につまずきやすいのが、この「シーン」という言葉です。名前が同じなのに、指しているものの範囲がまったく違います。
Unityでは、役割が2つの概念に分かれています。
- Scene: ステージやレベルという「大きな入れ物」。基本的に入れ子にはしない
- Prefab: 使い回す「部品」。Sceneの中に配置する
一方Godotには、この区別そのものがありません。 プレイヤー1体もシーン、ステージもシーン、ゲーム全体もシーン ——大小を問わずすべてが同じ「シーン」で、シーンの中にシーンを入れ子にして組み上げていきます。

頭の中の対応表はこうなります。
| Unityの概念 | Godotでの対応 |
|---|---|
| Scene(レベル/ステージ) | ただの「大きなシーン」(メインシーンとして起動する) |
| Prefab | シーン(.tscn)をインスタンス化して使う |
| GameObject + Component | ノード(機能は子ノードを足して盛る) |
つまり、この記事で解説した「シーンのインスタンス化」は、 Unityで言えば「Prefabをステージに配置する」感覚 です。「シーンを入れ子にする」という言葉に身構えず、 「GodotではPrefabに当たるものまで全部シーンと呼ぶ」 と捉え直すと、一気に腑に落ちるはずです。