godot-ui について
Godot 4.3以降のControlノード、レイアウト、テーマ、フォーカス、UIパターンを扱うスキルです。GDScriptやC#でメニューなどのゲームUIを作る開発者を支援します。
主な機能
- 01Controlの階層とレイアウト
- 02コンテナとアンカーの指針
- 03テーマとStyleBoxの設定
- 04キーボードとゲームパッドのフォーカス移動
- 05メニュー、設定、ポーズ画面のパターン
- 06シグナルと折りたたみUI要素
活用シーン
- 01メインメニューや設定画面を作る
- 02HUDやダイアログパネルを配置する
- 03キーボードとゲームパッドの操作に対応する
- 04折りたたみパネルや多重ラベル効果を作る
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill godot-uiインストール後、Claude Code で/godot-uiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anchors-in-code.mdfocus-and-navigation.mdfoldable-container.mdsignals.mdtheme-system.mdui-patterns.md詳細
Godot UI — Control ノード、テーマ、レイアウト
すべての例は、非推奨 API を使わずに Godot 4.3 以降を対象としています。まず GDScript、次に C# を扱います。
関連スキル: マルチ解像度でのスケーリングには responsive-ui、ゲーム内 HUD のパターンには hud-system、会話 UI の表示には dialogue-system、UI のトランジションやアニメーション効果には tween-animation を参照してください。
1. Control ノードの階層
Control と Node2D の違い
Control はすべての UI ノードの基底クラスです。Node2D/Node3D とは別のシーンツリー分岐に属し、レイアウトモデルも根本的に異なります。
| 特徴 | Node2D | Control |
|---|---|---|
| 位置のモデル | ワールド座標の position(親からのピクセル単位の位置) | 親の矩形を基準としたアンカーとオフセット |
| サイズ | 固有サイズなし | size、custom_minimum_size、計算された最小サイズ(get_combined_minimum_size())を持つ |
| テーマ | なし | Theme リソースを継承および上書き |
| フォーカス | 該当なし | 組み込みフォーカスシステム(focus_mode、grab_focus()) |
| マウスイベント | _input を使って手動で処理 | gui_input、mouse_entered、mouse_exited |
| レイアウト補助 | なし | Container サブクラスが子ノードを自動配置 |
基底クラスとしての Control
すべての UI ウィジェット(Button、Label、LineEdit など)は Control を継承します。Control 自体に定義されている主なプロパティは次のとおりです。
anchor_left、anchor_top、anchor_right、anchor_bottom— 親の矩形を基準とした割合値(0.0~1.0)offset_left、offset_top、offset_right、offset_bottom— アンカーの解決後に適用されるピクセル単位のオフセットsize_flags_horizontal、size_flags_vertical—Containerのレイアウトにおけるノードの配置方法theme—Themeリソース。参照時は、該当するリソースを持つ各祖先のControl/Windowを最も近いものから順に調べ、どちらでもない最初の親(例:CanvasLayerまたはNode2D)で探索を終了しますfocus_mode— ノードがキーボード/ゲームパッドのフォーカスを受け取れるかどうか
UI ノードは CanvasLayer 内に配置すると、Camera2D のトランスフォームの影響を受けずに、3D/2D ワールドより手前に描画されます。シーンルートに組み込まれているキャンバス(レイヤー 0)上の Control は、カメラがそのキャンバスのトランスフォームを設定するため、Camera2D と一緒に移動します。
⚠️ Godot 4.7 での変更点:
Control.accessibility_liveの型がDisplayServer.AccessibilityLiveModeからAccessibilityServer.AccessibilityLiveModeに変更されました(デフォルトはLIVE_OFF = 0、ほかにLIVE_POLITE、LIVE_ASSERTIVE)。アクセシビリティ関連の列挙型/API は、新しいAccessibilityServerシングルトンに移動しました。GDScript との互換性はありますが、C# のバイナリ/ソース互換性は失われるため、新しい列挙型に対して再ビルドが必要です。詳細は4.7 移行ガイドを参照してください。
2. よく使うコンテナーノード
| コンテナー | 目的 | 使用する場面 |
|---|---|---|
VBoxContainer | 子を垂直に積み重ねます | リスト、オプションの行、垂直メニュー |
HBoxContainer | 子を水平に並べます | ツールバー、ステータスの行、水平ナビゲーション |
GridContainer | 子を列数固定のグリッドに配置します | インベントリのグリッド、キー割り当ての表 |
MarginContainer | 単一の子の周囲にパディングを追加します | 任意のノードを囲み、余白を設ける場合 |
PanelContainer | StyleBox の背景を描画してから、子を配置します | カード UI、ダイアログボックス、HUD パネル |
ScrollContainer | 単一の子をスクロール可能にし、はみ出した部分をクリップします | 長いリスト、ログ、スクロール可能な設定 |
TabContainer | 子を名前付きタブとして重ね、同時に 1 つだけ表示します | 設定画面、複数セクションのパネル |
サイズ設定のヒント:
- 利用可能なスペースを埋める必要がある子には、
size_flags_horizontal = SIZE_EXPAND_FILLを設定します。 - 子がゼロまで縮まないよう、
custom_minimum_sizeを使用します。 MarginContainerはテーマプロパティmargin_*からマージンを読み取ります。実行時にadd_theme_constant_override("margin_left", 16)で上書きできます。
Godot 4.7 以降:
custom_maximum_size(Vector2(-1, -1))は軸ごとにサイズの上限を設定し、custom_minimum_sizeより優先されます。propagate_maximum_size(デフォルトはfalse)を有効にすると、親の最大サイズが子の Control のサイズを制限します。_get_maximum_size()はコードから最大サイズを計算します。
⚠️ Godot 4.7 での変更点:
TabContainer.all_tabs_in_frontは非推奨です。タブは常に前面に表示されるようになったため、このプロパティは何もしません。設定しているコードを削除してください。GH-118623 を参照してください。
3. アンカーとマージン
アンカーのプリセットの仕組み
アンカーとは、親の矩形上の点を割合で表したものです(0 = 上端/左端、1 = 下端/右端)。Godot は、各辺の最終的なピクセル位置を次のように算出します。
final_left = parent_width * anchor_left + offset_left
final_top = parent_height * anchor_top + offset_top
final_right = parent_width * anchor_right + offset_right
final_bottom = parent_height * anchor_bottom + offset_bottom
エディターには、組み込みのプリセットが用意されています。
| プリセット | アンカー値 | 使用例 |
|---|---|---|
| 全矩形 | L=0, T=0, R=1, B=1 | 親に重ねる/親を埋める — ルート UI で最も一般的 |
| 中央 | L=0.5, T=0.5, R=0.5, B=0.5 | 親の中央に配置する固定サイズのウィジェット |
| 左上 | L=0, T=0, R=0, B=0 | 左上隅に固定する固定サイズのウィジェット |
| 右上 | L=1, T=0, R=1, B=0 | 右上隅に固定する固定サイズのウィジェット |
| 下中央 | L=0.5, T=1, R=0.5, B=1 | 下中央にアンカーする HUD 要素 |
コードでアンカーを設定する
アンカーは辺ごとに parent_size * anchor + offset として算出されるため、手動で設定するには 8 つのプロパティを指定する必要があります。set_anchors_and_offsets_preset(Control.PRESET_*) なら 1 回の呼び出しで設定できます。まずこれを使用し、その後、マージンを調整するために offset_* を設定します(右端/下端では負の値を指定します)。
アンカーとオフセットのルール(オフセットは 0 のままにし、アンカーで配置する)に加え、GDScript と C# の完全な例(全矩形への拡張、16 px のマージンを付けた右上 HUD、画面の半分を占めるカスタムサイドパネル)については、references/anchors-in-code.md を参照してください。
4. テーマシステム
Theme リソースを使うと、フォント、色、StyleBox を一元管理できます。ルートに適用し、継承を活用してください。theme_override_* は個別の調整にのみ使用します。ほとんどのフラットデザインのニーズには StyleBoxFlat(bg_color、border_color、corner_radius_*、border_width_*)が適しています。テクスチャには StyleBoxTexture を使用します。
Theme リソースの作成手順、StyleBoxFlat のプロパティ、フォントのオーバーライド、テーマの継承ルール、ノードごとの
theme_override_*メソッドの詳細については、references/theme-system.md を参照してください。
Godot 4.7 以降:
GradientTexture2DのFillenum にFILL_CONICが追加されました。円錐状(角度ベース)のパターンで色を補間します。シェーダーなしで放射状の進捗/クールダウンインジケーターを作成できます(C#:FillEnum.Conic)。
5. フォーカスとナビゲーション
フォーカスモード(FOCUS_NONE、FOCUS_CLICK、FOCUS_ALL)によって、キーボード/ゲームパッドでのナビゲーションが制御されます。focus_neighbor_top/_bottom/_left/_right を使ってフォーカスチェーンを設定するか、自動的な空間検出を利用します。メニューを開くときは、最初のインタラクティブ要素で grab_focus() を呼び出してください。
フォーカスモードの詳細、
focus_neighborチェーンの例、ゲームパッド/キーボード入力の処理、grab_focusのパターンについては、references/focus-and-navigation.md を参照してください。
6. 一般的な UI パターン
基本となるシーンは 3 つあります。メインメニュー(タイトルとボタンリストを配置した、中央揃えの VBoxContainer)、タブ付き設定画面(カテゴリごとの子パネルを持つ TabContainer)、一時停止メニューのオーバーレイ(全画面の ColorRect 背景と中央揃えのオプションパネルを配置し、get_tree().paused = true で一時停止)。
各パターンのシーンツリーの全フラグメントと GDScript による接続方法については、references/ui-patterns.md を参照してください。
Godot 4.7 以降:
offset_transform_*— コンテナのレイアウトを再実行しない、視覚効果専用の UI 変形(シェイク/パルス)。_get_cursor_shape(at_position)— 位置ごとのカーソル形状。PopupMenuの検索バー(デフォルトであいまい検索が有効なsearch_bar_enabled)と、並べ替え用のset_item_index()。TextureRectのSTRETCH_TILEがAtlasTextureをタイル表示するようになりました(サポートされないのはゼロ以外のmarginのみです)。コードについては、references/ui-patterns.md を参照してください。
⚠️ Godot 4.7 で変更:
RichTextLabel.add_image()/update_image()のサイズ指定が再設計され、width/heightはfloatになりました。width_in_percent/height_in_percentの bool はwidth_unit/height_unitに変わり、新しいImageUnitenum(IMAGE_UNIT_PIXEL、IMAGE_UNIT_PERCENT、IMAGE_UNIT_EM。em はフォントサイズに応じて拡大縮小します)を指定します。ImageUpdateMask.UPDATE_WIDTH_IN_PERCENTはUPDATE_WIDTH_UNITに改名され、旧名を使う GDScript は動作しなくなります。4.7 移行ガイドを参照してください。
7. シグナル
クリックには Button.pressed、ノードで発生する生イベントには Control.gui_input、ホバーには Control.mouse_entered/mouse_exited を使います。_ready() 内、またはインスペクターの Node パネルから接続してください。
シグナルの完全なカタログと、シグナル駆動型の UI 更新パターンについては、references/signals.md を参照してください。
8. FoldableContainer(Godot 4.5 以降)
FoldableContainer は Godot 4.5 で追加された、組み込みのアコーディオン型 Container です。トグル式ヘッダーと折りたたみ可能な子要素を備え、Button から VBoxContainer の表示/非表示を切り替える従来の定型コードを置き換えます。title を設定し、初期状態を folded で指定して、通常どおり子要素を追加し、folding_changed(is_folded) を待ち受けます。
GDScript と C# での構築方法、主要プロパティの表、トグルシグナルについては、references/foldable-container.md を参照してください。
9. ラベルへのエフェクト重ねがけ(Godot 4.5 以降)
Godot 4.5 では、LabelSettings リソースを使って、Label に複数のアウトラインとシャドウを重ねられます。たとえば、幅や色の異なる 2 つのアウトラインと、柔らかなドロップシャドウを設定できます。このスタックはテーマオーバーライドではなく LabelSettings 上にあり(インデックスごとに設定します)、RichTextLabel には同等の機能がありません。以前は複数のアウトラインを重ねるには、Label ノードを複製して手動で重ねる必要がありました。
# Stacked effects live on LabelSettings and are configured per index.
func apply_stacked_outlines(label: Label) -> void:
var settings := LabelSettings.new()
settings.outline_size = 4 # base (inner) outline
settings.outline_color = Color.BLACK
settings.add_stacked_outline() # stacked outline 0, drawn outside the base one
settings.set_stacked_outline_size(0, 8)
settings.set_stacked_outline_color(0, Color.GOLD)
settings.add_stacked_shadow() # stacked shadow 0
settings.set_stacked_shadow_offset(0, Vector2(3, 3))
settings.set_stacked_shadow_color(0, Color(0.0, 0.0, 0.0, 0.5))
settings.set_stacked_shadow_outline_size(0, 2)
label.label_settings = settings # takes priority over theme properties
public void ApplyStackedOutlines(Label label)
{
var settings = new LabelSettings { OutlineSize = 4, OutlineColor = Colors.Black };
settings.AddStackedOutline();
settings.SetStackedOutlineSize(0, 8);
settings.SetStackedOutlineColor(0, Colors.Gold);
settings.AddStackedShadow();
settings.SetStackedShadowOffset(0, new Vector2(3, 3));
settings.SetStackedShadowColor(0, new Color(0f, 0f, 0f, 0.5f));
settings.SetStackedShadowOutlineSize(0, 2);
label.LabelSettings = settings;
}
RichTextLabel ではエフェクトを重ねられません。BBCode を使って、テキストの各範囲に 1 つのアウトラインを指定します:[outline_size=4][outline_color=#000000]Level Up![/outline_color][/outline_size]。
エディターでの作業手順: Label の Label Settings プロパティで
LabelSettingsリソースを作成し、積み重ねるアウトラインとシャドウのリストに項目を追加します。上記のインデックスごとの呼び出しは、動的な設定に使用します。
10. チェックリスト
- ルート UI
Controlのアンカープリセットが Full Rect(またはレイアウトに適したプリセット)に設定されている - すべてのインタラクティブなウィジェット(
Button、LineEdit、Slider)のfocus_modeがFOCUS_ALLに設定されている - 装飾用ノード(
Label、TextureRect)のfocus_modeがFOCUS_NONEに設定されている - 非線形レイアウトではフォーカス移動先が設定され、ゲームパッドで正しく循環移動できる
- 各画面で、最初のインタラクティブなウィジェットに対して
_ready()内でgrab_focus()が呼び出されている - ポーズメニューのルート
Controlのprocess_modeがPROCESS_MODE_ALWAYSに設定されている - 画面のルートに
Themeリソースが1つ割り当てられている。すべての子ノードに重複して割り当てられていない - 単色のシンプルなパネルには、画像アセットではなく
StyleBoxFlatが使われている - ノードごとの上書きには、
Theme全体を新たに割り当てるのではなくadd_theme_*_override()が使われている - 手動で
positionの値を設定するのではなく、レイアウトにコンテナ(VBoxContainer、HBoxContainerなど)が使われている - ゼロサイズに縮小してはならないウィジェットに
custom_minimum_sizeが設定されている - スライダーと音量のコードでは、オーディオバスに割り当てる際に生の線形値ではなく
linear_to_db/db_to_linearが使われている - シグナルは
_ready()内(またはエディター経由)で接続されている。_process内で UI の状態をポーリングしていない -
TabContainerのタブ順序が、論理的な読み取り順/ナビゲーション順と一致している - アコーディオン形式の折りたたみ可能なパネルには、手動で
ButtonとVBoxContainerを連携させるのではなくFoldableContainerが使われている(Godot 4.5+) -
Labelに複数のアウトライン/シャドウレイヤーを設定する際は、ノードを複製するのではなく、LabelSettingsでアウトライン/シャドウを重ねている(Godot 4.5+)