ボタンを画面に置いたはいいけれど、スマホでは端で見 切れ、PCでは真ん中にぽつん——UIの位置を position で手で決めていると、画面サイズが変わるたびにレイアウトが崩れて頭を抱えることになります。
Godotはこれを、Controlノード と レイアウトコンテナ で解決します。「ここは縦に並べる」「ここは中央に置く」といったルールを決めておけば、あとはGodotが画面サイズに合わせて自動で配置してくれます。座標を1つずつ指定する作業から解放されるわけです。
この記事でわかること
Controlノードの アンカー で、画面サイズに追従させる考え方VBox・HBox・Gridなど主要 レイアウトコンテナ の使い分け- コンテナを 入れ子 にして、設定画面のような複雑なUIを組む方法
- Size Flags(Fill / Expand / Stretch Ratio)でスペースの分配を制御する
Controlノードとアンカー
UI要素の基盤になるのが Controlノード です。Sprite2D などの Node2D と同じく画面に描画されますが、UIならではの機能を持っています。
- アンカーとオフセット :親のどの位置を基準に、どれだけずらして配置するかを決めます。画面サイズが変わってもレイアウトを保つ鍵です。
- 入力処理 :ボタンのクリックやスライダー操作など、UI特有の入力を扱うシグナルを備えています。
- テーマ :色やフォントを一元管理する仕組みに対応します(テーマシステムによる統一的なUI設計 参照)。
とくに大事なのが アンカー です。「上辺は親の上に、下辺は親の下に固定」のように四隅の基準を決めておくと、画面が大きくても小さくても、UIがそれに追従します。

Full Rect(親いっぱいに広がる)、Center(中央)などのプリセットがインスペクタの「レイアウト」メニューにあるので、まずはここから選ぶのが手軽です。
レイアウトコンテナで自動整列する
アンカーで1つ1つ配置してもよいのですが、「ボタンを縦に3つ」のような並びは、手で座標を決めるより レイアウトコンテナ に任せる方が圧倒的に楽です。
コンテナは、子のControlノードのサイズと位置を 自動で並べてくれる 特殊なControlノードです。開発者は座標ではなく「どう並べたいか」だけを考えればよくなります。

よく使うコンテナは次の通りです。
| コンテナ | 並べ方 | よくある用途 |
|---|---|---|
| VBoxContainer | 子を縦に並べる | メインメニュー、設定項目リスト |
| HBoxContainer | 子を横に並べる | ツールバー、OK/キャンセルボタン |
| GridContainer | 子を格子状に並べる | インベントリ、スキルツリー |
| MarginContainer | 子の周囲に余白を足す | 画面外周の安全な余白 |
| CenterContainer | 子を中央に置く | タイトルロゴ、ポップアップ |
| PanelContainer | 背景パネルを描いて子を内側に | ウィンドウの背景 |
| ScrollContainer | はみ出したらスクロールバー | 長いリスト、可変数のアイテム |
格子状に並ぶ GridContainer は、まさに インベントリシステム設計の基礎 のようなマス目UIで活躍します。
Size Flagsでスペースを分配する
コンテナ内で子のサイズをどう扱うかを決めるのが Size Flags です。
- Fill :割り当てられたスペースを埋めるように広がる
- Expand :コンテナの余ったスペースを分け合って占有する
たとえば縦に並べた3つのボタンすべてに Expand を付けると、3つが高さを均等に分け合います。1つだけ2倍の高さにしたいときは、そのボタンの Stretch Ratio を 2 にします。

「均等に並べたい」「1つだけ大きく」といった調整が、座標計算なしにプロパティだけで決まるのがコンテナの強みです。
実践:設定画面をコンテナの入れ子で組む
実際のUIは、コンテナを 入れ子 にして組みます。RPGでもFPSでもパズルでも、「外周に余白 → 項目を縦に並べる → 各項目は名前と入力を横に並べる」という設定画面の骨組みはだいたい共通です。

役割ごとにコンテナを重ねると、次のようになります。
MarginContainer … 画面外周に余白を確保
└─ VBoxContainer … 設定項目を縦に並べる
├─ Label … 見出し「グラフィック設定」
├─ HBoxContainer … 「解像度」+ドロップダウンを横に
│ ├─ Label
│ └─ OptionButton
├─ HBoxContainer … 「フルスクリーン」+チェック
│ ├─ Label
│ └─ CheckBox
└─ HBoxContainer … 「適用」ボタンを右寄せ
├─ Control … 空白でスペースを押し出す(H:Expand)
└─ Button
ボタンを右寄せにしたいときは、HBoxContainer の中に 空の Control を1つ置いて、Size Flags の Horizontal に Expand を付ける のが定番です。この空白が余白を全部吸って、ボタンを右へ押しやってくれます。
コード側は、いつも通りシグナルを繋ぐだけです。UI部品同士を疎結合につなぐ考え方は シグナルによるノード間の連携 を参照してください。
extends Control
# シーンユニークノード(%)で参照すると、パスの変更に強い
@onready var apply_button: Button = %ApplyButton
func _ready() -> void:
apply_button.pressed.connect(_on_apply_pressed)
func _on_apply_pressed() -> void:
print("設定を適用")
このパネルは、丸ごと .tscn として保存すれば、タイトル画面でもポーズメニューでも同じ設定画面を使い回せます。
よくある間違いとベストプラクティス
いちばん多いのが、コンテナを使わず position を手で指定してしまうことです。作った画面では綺麗でも、解像度が変わると崩れます。

| よくある間違い | ベストプラクティス |
|---|---|
すべて手動配置で position を直接いじる | コンテナに任せ、手動調整は最小限にする |
| 画面サイズごとに位置を調整するコードを書く | アンカーとSize Flags でGodotのレスポンシブ機能に任せる |
| 色やフォントを各ノードで個別設定する | Theme リソース で見た目を一元管理する(テーマの記事) |
| 巨大な1シーンにUIを全部詰める | HPバーやボタンなど再利用部品は 個別シーン にして使い回す |
get_node("長い/パス") を多用する | @onready とシーンユニークノード % で参照を堅牢にする |
おまけ:先に知っておくと良いこと
_draw()でカスタム描画 :コンテナでは作れないグラフや独自形状のゲージは、Controlの_draw()で線や円を直接描けます。- ネストは深くしすぎない :コンテナは便利ですが、何百もの子や深すぎる入れ子はリサイズ再計算のコストになります。意味のあるまとまりで区切りましょう。
- 長いリストは
ScrollContainer:数百項目を一度に作らず、見える範囲だけ生成すると軽くなります。 - 見た目を揃えるなら Theme :色・フォント・余白をまとめて管理すると、UI全体の統一感が出ます(テーマシステムによる統一的なUI設計)。
まとめ
- Controlノード :UIの基盤。アンカーで画面サイズに追従させる
- レイアウトコンテナ :VBox / HBox / Grid などが子を自動で整列。座標指定から解放される
- 入れ子 :Margin > VBox > HBox のように重ねて、設定画面のような複雑なUIを組む
- Size Flags :Fill / Expand / Stretch Ratio でスペースの分配を制御する
まずは VBoxContainer にボタンを3つ並べるところから始めて、MarginContainer や HBoxContainer を重ねて設定画面へ、と広げていきましょう。次は、作ったUIの見た目を一括で整える テーマシステムによる統一的なUI設計 に進むのがおすすめです。