【Godot】Godot学習ロードマップ:ノード1つから、1本のゲームが動くまでをどの順で覚えるか

作成: 2026-09-22最終更新: 2026-10-10

チュートリアルのあとに何をどの順で覚えるかを、1つの小部屋へ機能を7段で足していく形で解説します。

チュートリアルを終えて自分のゲームを作り始めるときに迷うのが、何をどの順で覚えるかです。ゲームは、動いて、当たって、数えて、終わる、の4つが1周したときに初めて遊べます。この1周を先に作れば、絵や音を足すたびに遊んで確かめられます。

順番を決めずに始めると、何から作ればいいかで手が止まったり、キャラの絵を描き直しているうちに、遊べる形になる前に止まったりします。

この記事では、1つの小部屋に機能を7段で足していく順番と、各段で読む記事を解説します。

小部屋を進む人形と、足元のコイン・旗・音符。1つの部屋に、機能を1段ずつ順に足していく

この記事でわかること

  • ゲームを遊べる形にする「動く・当たる・数える・終わる」の1周
  • 最初に役割を覚えるノード5つ
  • 1つの部屋に足していく7段と、各段の到達点
  • 後回しでいいものと、3Dへ移る時期

動作確認環境: Godot 4.7

Sponsored

ゲームが遊べる形:動く・当たる・数える・終わる

画面の四角をゲームにしているのは、絵でも音でもありません。自分が動いて何かに当たり、当たった数が数えられて、決まったところで終わります。終わったら、もう一度最初から遊べます。この4つが1周すれば、四角と数字だけでもゲームです。

動く・当たる・数える・終わるが1周すると遊べる。終わるが無いまま見た目や音を足しても遊べない

何から作るかは、1周に要る最小のもの、つまり床と四角とコインで決まります。絵や音は1周したあとで足します。

1つの小部屋に足していく作り方

これから作るのは、四角い床が1枚あるだけの小部屋です。床の上には、自分が1人、動かない敵が1体、コインが3枚あります。ここに7つの段で機能を足していきます。

大事なのは、毎回ゲームを作り直さないことです。今日置いた床を残したまま、明日は当たり判定を足し、その次の日に数字を出します。前に覚えたことが、そのまま次の土台になります。

シーンの分け方にも順番があります。チュートリアルの多くは、Player.tscn・Enemy.tscn・Coin.tscn を先に切り出させます。自分で作り始めるときは逆で、最初は全部を1つのシーンに置いておくほうがつまずきません。

切り出すのは、同じものをまとめて直したくなったときです。コインを3枚並べるだけなら複製で足ります。3枚の見た目を一度に変えたくなったら、そこで Coin.tscn に切り出します。

最初に覚えるノード5つ

Godotのノードは数百あります。全部を知る必要はなく、最初に役割を掴むのは5つで足ります。画面のどこに何があるかが怪しいなら、先に エディタ入門 を1本読んでおくと迷いません。

  • Node2D: 部屋や物をまとめる入れ物。位置を持つ
  • CharacterBody2D: 操作して動かすもの。壁にぶつかると止まる
  • StaticBody2D: 動かないもの。進路をふさぐ
  • CollisionShape2D: 当たる形を決める。動くもの・動かないもの・エリアのどれにも、子として付ける
  • Area2D: 入ってきた相手に気づく。止めはしない
Node2D・CharacterBody2D・StaticBody2D・CollisionShape2D・Area2Dの5つと、それぞれの役割

床や四角を描く ColorRect、数字を出す Label も使いますが、役割を先に掴むのはこの5つです。

この中でいちばん取り違えやすいのが、最後の2つの関係です。体でふさぐのと、エリアで気づくのは別物です。壁は通れなくするもので、コインは触れたことを知らせるものです。同じ「当たった」でも担当が違います。

体でふさぐと止まり、エリアで気づくと通り抜けながらコインが消える。同じ「当たった」でも担当が違う

壁で止まるのは CharacterBody2D と StaticBody2D、コインや敵に気づくのは Area2D です。この2系統を先に分けておくと、「当たっているのに消えない」で止まりません。

他のエンジンでいうと: Area2D は、Unity の Collider2D で「Is Trigger」をオンにしたもの(OnTriggerEnter2D で気づく)、Unreal Engine の Overlap イベントに近い仕組みです。Godot では、ふさぐか気づくかをノードの種類で分けています。

当たる相手を決める Collision Layer と Mask は、新規プロジェクトの既定のままで、この記事の実践は動きます。

Sponsored

学ぶ順番の7段

同じ部屋に、次の順で足していきます。各段には「ここで止めてもいい」到達点があります。画面でそれが起きていれば、次へ進んで構いません。

動く・当たる・数える・終わる・見た目・音・残すの7段を、1本の道に立つ立て札で示した地図

第1段:動く

床を囲むように壁を置き、矢印キーで上下左右に動かします。壁で止まるところまでが1段目です。横スクロールで作る場合も、ジャンプはまだ要りません。

到達点: 矢印キーでキャラが床の上を動き、壁で止まる。

見下ろしで動かすなら、CharacterBody2D の Motion Mode を Floating にします(Motion Mode)。移動を書く場所は ゲームループ の記事にあります。WASD でも動かしたくなったら、Input Map で自分の操作を作ります。

第2段:当たる

コインと敵を置きます。どちらも Area2D です。コインは触れると消え、敵は触れると何かが起きるようにします。敵は動かなくて構いません。

到達点: コインに触れると消え、敵に触れると反応がある。

Area2D が主役の段です。止まる側との違いは 2D物理ボディ にまとまっています。

第3段:数える

取ったコインの枚数を画面に出します。変数を1つ増やして Label に書くだけです。

到達点: 画面隅の数字が、取るたびに増える。

数の持ち方は GDScript入門 にあります。あとでコインを別のシーンに分けたら、取られたことを数字の側へ知らせる方法は シグナル です。

第4段:終わる

3枚集めたらクリア、敵に当たったら失敗にして、キー1つで最初から遊べるようにします。動く・当たる・数える・終わるの1周がつながるのが、この段です。

到達点: 規定数でクリア表示が出て、失敗してもエディタに戻らずにやり直せる。

やり直しの1キーを後回しにすると、遊ぶたびにエディタへ戻って F5 を押すことになります。この手間が重なると、作っている本人が自分のゲームを遊ばなくなります。

タイトルとゲームオーバーの画面まで作るなら ゲーム進行入門、一時停止を足すなら ポーズ が次の一歩です。

第5段:見た目

四角を絵に差し替え、向きを変え、取った瞬間に何か光らせます。ここで初めて Sprite2D が出てきます。

到達点: 左右で絵が向き、コインを取ったことが目で分かる。

絵の切り替えは AnimatedSprite2DとAnimationPlayer 、被弾の白フラッシュは modulate 、追従カメラは Camera2D 。床をタイルにしたくなったら TileMapLayer へ進みます。

描き直しから始めないでください。今動いているキャラのまま、演出だけを足します。絵を描き直し始めると、ゲームではなく素材フォルダが育ちます。

第6段:音

取得・被弾・クリアに音を付けます。第5段より簡単です。

到達点: 3つの場面で音が鳴り、音を切ってもゲームは成立している。

オーディオ入門 でBGMと効果音の音量を分けるところまでやれば足ります。

ここでよく踏むのが、コインに音を付けて、ノードを消す queue_free() の直前で鳴らす形です。ノードごと消えるので音も切れます。音を出す側は、消える相手ではなく残るほう(この記事の実践なら Main)に置いてください。

第7段:残す

ここは任意です。最高記録を1つだけファイルに書いて、次の起動でも残るようにします。

到達点: 閉じて開き直しても、前回の記録が出ている。

書く先は、ゲームごとに用意される保存用のフォルダ user:// です。本格的なセーブは セーブ/ロード にありますが、1つの部屋で遊ぶだけなら数値1つで十分です。

Sponsored

実践:動いて終わるまでを1つの部屋で作る

見下ろしのアクションRPGの1部屋、迷路の1面、弾をよける1画面 —— ジャンルは違っても、最初に遊べる形はどれも同じ4つでできています。第1段から第4段までを、1つのシーンと1本のスクリプトで作ります。

実践で作る部屋。左にプレイヤー、中央に敵、上に2枚と下に1枚のコイン、左上にスコアと案内

① 置くもの

新規プロジェクトで2Dシーンを作り、main.tscn として保存して、F5 で最初に開くメインシーンに指定します。

Main (Node2D)            ← main.gd
├── Floor (ColorRect)
├── Walls (StaticBody2D)
│   └── CollisionShape2D × 4
├── Player (CharacterBody2D)
│   ├── ColorRect
│   └── CollisionShape2D
├── Coins (Node2D)
│   └── Coin1 / Coin2 / Coin3 (Area2D、それぞれ ColorRect と CollisionShape2D を持つ)
├── Enemy (Area2D)
│   ├── ColorRect
│   └── CollisionShape2D
└── Hud (CanvasLayer)    ← カメラが動いても、画面に貼り付いたまま描く層
    ├── ScoreLabel (Label)
    └── MessageLabel (Label)

値はこう置きます。CollisionShape2D の Shape は最初は空なので、どれも New RectangleShape2D を選んで形を作り、Size を下の大きさに合わせます。

  • Floor: Position (88, 108)、Size (976, 432)、Color は #CCCCCC(明るい灰色)
  • Walls 自身は (0, 0)。その下の4つの形は 上 (576, 96) 1000 × 24、下 (576, 552) 1000 × 24、左 (76, 324) 24 × 456、右 (1076, 324) 24 × 456
  • Player: (200, 324)、32 × 32、水色。Motion Mode を Floating
  • Coin1 (400, 200) / Coin2 (576, 460) / Coin3 (880, 200):24 × 24、明るい青
  • Enemy: (640, 324)、48 × 48、濃紺
  • ScoreLabel は (88, 24)、MessageLabel は (88, 56)

見た目の ColorRect と当たる形の CollisionShape2D は、原点の位置が違います。ColorRect は左上が原点なので、同じ大きさにしたうえで、大きさの半分だけ左上へずらします。

ColorRectは左上が原点、CollisionShape2Dは中心が原点。ColorRectを半分ずらすと中心がそろう

ずらす量は、Player なら (-16, -16)、コインは (-12, -12)、Enemy は (-24, -24) です。プレイヤー・コイン・敵の CollisionShape2D は (0, 0) のままで構いません。位置を動かす形は、壁の4つだけです。

床は ColorRect だけで、当たり判定を持ちません。止めているのは Walls に付けた4つの形です。壁の形を複製で増やしたときは、Size を変える前に Shape の欄のメニューから Make Unique を選んでください。複製したままだと4つが同じ形を共有していて、1つの大きさを変えると全部が変わります。

② スクリプトを書く

Main に1本だけ付けます。プレイヤーにスクリプトは要りません。

# main.gd(Main にアタッチ)
extends Node2D

const SPEED := 240.0   # 1秒に進むピクセル数
const TARGET := 3

var score := 0
var finished := false

@onready var player: CharacterBody2D = $Player
@onready var score_label: Label = $Hud/ScoreLabel
@onready var message_label: Label = $Hud/MessageLabel

func _ready() -> void:
	for child in $Coins.get_children():
		var coin := child as Area2D
		coin.body_entered.connect(_on_coin_touched.bind(coin))
	$Enemy.body_entered.connect(_on_enemy_touched)
	_update_score()
	message_label.text = "矢印キーで動いて、コインを3枚集める"

func _physics_process(_delta: float) -> void:
	if finished:
		return
	# 押している矢印キーから、長さ1までの向きを作る
	var direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	player.velocity = direction * SPEED
	player.move_and_slide()          # 壁で止まるのはこの1行

func _on_coin_touched(body: Node2D, coin: Area2D) -> void:
	if finished or body != player:
		return
	coin.queue_free()
	score += 1
	_update_score()
	if score == TARGET:
		_finish("クリア")

func _on_enemy_touched(body: Node2D) -> void:
	if finished or body != player:
		return
	_finish("敵に当たった")

func _update_score() -> void:
	score_label.text = "コイン %d / %d" % [score, TARGET]   # %d の位置に、右の配列の数が順に入る

func _finish(text: String) -> void:
	finished = true
	player.velocity = Vector2.ZERO
	message_label.text = text + " Enterでやり直し"

# ボタンなどの UI が使わなかった入力だけが、ここへ届く
func _unhandled_input(event: InputEvent) -> void:
	if finished and event.is_action_pressed("ui_accept"):
		get_tree().reload_current_scene.call_deferred()   # このフレームの処理を終えてから、シーンを最初から読み直す

ui_left や ui_accept はGodotに最初から入っているので、Input Map の設定は要りません。move_and_slide() に delta(前のフレームからの経過秒数)を掛けないのは、この関数が時間を見てくれるからです。

3枚のコインのシグナルは、エディタで1枚ずつ接続する代わりに、_ready() でまとめて接続しています。bind(coin) は、シグナルが渡す引数(触れた相手の body)の後ろに、そのコイン自身を足しておく書き方です。3枚を同じ関数につないでも、どのコインに触れたかが分かります。

body != player で相手を確かめているのは、Collision Layer と Mask を既定のまま使っているからです(Collision LayerとMask)。

③ 動かして確かめる

コイン 0 / 3 から 2 / 3 へ増え、3枚目でクリアが出て、Enter で最初の部屋へ戻る

F5で実行して、矢印キーで動かします。見るのは3つです。

まず、床の端まで進むと止まります。床の外へ出てしまうなら、Debug メニューの Visible Collision Shapes をオンにして実行し、壁の形の位置と大きさを確かめます。4つの形が (0, 0) に集まったままになっていることがよくあります。

次に、コインに触れると消えて、左上の数字が「コイン 1 / 3」に変わります。消えないならそのコインの Shape を、数字が読めないなら2つのラベルの位置を先に確かめます。

仕上げに、3枚すべてを取ります。上の2枚を取ってから右を回って下へ向かえば、敵に触れずに集められます。3枚目で「クリア Enterでやり直し」と出てプレイヤーが止まり、Enter を押すと、コインが3枚そろった部屋から遊び直せます。途中で敵に触れても「敵に当たった」と出て、同じように Enter で戻れます。エディタに戻らずに、何度でも遊べます。

ポイントは2つです。

  • 止める係と気づく係を分ける: 壁で止めているのは Walls の StaticBody2D と player.move_and_slide() です。コインと敵が反応しているのは Area2D の body_entered です。同じ「当たり」でも通る道が違うので、動かないときはどちらの話か先に決めます
  • やり直しを最初から入れておく: reload_current_scene() の1行があるだけで、自分のゲームを遊べるようになります。あとから足すつもりでいると、たいてい足さないまま飽きます

後回しでいいものと、3Dへ移る時期

Autoload、タイルマップ、アニメーションツリー、シェーダーは、どれも「先に覚えたほうがいい」ように見えますが、ほとんどは後で構いません。次のものは、必要になった瞬間に覚えれば間に合います。「覚えなくていい」ではなく「今の部屋で必要になった順に」という意味です。

  • Autoload: スコアや音楽をシーンまたぎで持ちたくなったら
  • TileMapLayer: 床を四角からタイルにしたくなったら
  • AnimationTree: 歩きと走りの切り替えが手に負えなくなったら
  • カスタムリソース: 敵の種類が増えて、数値を1か所にまとめたくなったら
  • NavigationAgent2D: 敵に障害物を避けさせたくなったら
  • UIレイアウト: 画面サイズが変わっても崩れない配置が要るとき。Label を1つ置くだけなら第3段でできます
  • シェーダー: 絵では作れない表現が要るとき

3Dへ移る時期も同じ考え方で、2Dを全部終えてからではなく、第4段で1周したら移れます。

動く・当たる・数える・終わるの4段を過ぎた地点で道が分かれ、3Dへも見た目・音・残すへも進める

3Dへ行くときだけは、同じ部屋に足すのではなく新しい部屋を作ります。それでも、そこまでに覚えた考え方はそのまま載ります。CharacterBody2D は CharacterBody3D、Area2D は Area3D、CollisionShape2D は CollisionShape3D に置き換わり、スコアの数え方も終わり方も変わりません。

新しく覚えるのは、向き(3Dでは y が空の方向)とカメラと見た目の作り方です。入口は Node3D入門・CharacterBody3D入門 です。

逆に、第5段の見た目まで2Dで仕上げてから移ろうとすると、たいてい移れません。絵とタイルとアニメには終わりがないからです。

Sponsored

うまくいかないときは

症状原因直し方
実行した直後に「Node not found」のエラーが出るスクリプトの $Player や $Hud/ScoreLabel と、ツリーのノード名・親子関係が違う名前を1文字ずつ合わせる。大文字と小文字も区別される
四角を絵に替えたら、見た目と当たり判定がずれたSprite2D は中心が原点なのに、ColorRect 用のずらしが残っている絵の Sprite2D の Position を (0, 0) にする。Player 本体は動かさない
プレイヤーを Area2D で作ったら、コインの body_entered が鳴らないArea2D どうしの重なりは、body_entered ではなく area_entered で届く壁で止まってほしいプレイヤーは CharacterBody2D で作る
あとから足したコインだけ取れない_ready() でつないだのは起動した時点のコインだけ。足したコインの body_entered はどこにもつながっていない足すときに coin.body_entered.connect(_on_coin_touched.bind(coin)) を呼ぶ

おまけ:先に知っておくと良いこと

  • 公式チュートリアルとは作りが違う: 公式の "Your first 2D game" は、プレイヤーを Area2D で作り、見た目を早めに整えます。覚える内容は重なりますが、この記事は作り直しを減らす順を選んでいます
  • 詰まったら print() で確かめる: 動かない原因は、たいてい思っている場所と違います。デバッグ入門 の道具を持ち替える手順が早道です
  • 書き出して人に渡すと続く: 遊べる形にすると感想が返ってきます。エクスポート入門 は第4段で1周した時点で読む価値があります

まとめ

  • 遊べるのは1周したとき: 動く・当たる・数える・終わるの1周。絵と音はそのあと
  • 作るのは1つの小部屋: 毎回作り直さず、同じ部屋に足していく
  • 最初の5つの役割: 体でふさぐのと、エリアで気づくのは別物
  • 順番: 動く → 当たる → 数える → 終わる → 見た目 → 音 → 残す
  • 分けどき、移りどき: シーンを分けるのは、同じものをまとめて直したくなったとき。3Dへ移るのは、2Dで1周したとき

まずは床と四角だけで、動いて終わるところまで作ってみてください。絵が無くても、1周すればそれはもうゲームです。あなたの最初の部屋では、プレイヤーに何を集めさせますか。

次に読む学習パスの次の記事
基礎

Godotエディタ入門:4つのドックの役割を覚えて、画像を1枚置いて実行する

この記事を読む
Godot このセクションのノート104