【Godot】テーマシステムによる統一的なUI設計 - 一貫性のあるデザイン実装

作成: 2025-12-08最終更新: 2026-07-08

GodotのテーマシステムでUIの見た目を一元管理する方法を、5つのアイテム・継承の優先順位・StyleBoxFlat・ダークモード切り替えの実装まで実例で解説します。

ボタンの色を少し変えたいだけなのに、シーンごとに置いた何十個ものボタンを1つずつ直す——UIのスタイルを各ノードで個別に設定していると、こんな終わりのない修正地獄にはまります。しかもシーンごとに微妙に見た目がズレて、なんとなく素人っぽいUIになりがちです。

これを解決するのが、Godotの テーマ(Theme)システム です。色・フォント・余白・ボタンのスタイルを 1つのデザインシステム としてまとめて管理し、テーマを差し替えるだけでUI全体の見た目を一斉に変えられます。ダークモード切り替えのような機能も、これで一気に現実的になります。

テーマ(色・StyleBox・フォントのパレット)がゲームUIパネル全体の見た目を統一しているイメージ図

この記事でわかること

  • Theme を構成する5つのアイテム(Color / Constant / Font / Icon / StyleBox
  • テーマが上から下へ流れる 継承 の仕組みと優先順位
  • StyleBoxFlat でボタンの normal / hover / pressed を作る方法
  • preload したテーマを差し替える ダークモード切り替え の実装

Sponsored

テーマを構成する5つのアイテム

GodotのUIはすべて Control から派生していて、その見た目は Theme リソースが決めます。Theme は、スタイルを定義する アイテム の集まりです。

Themeを構成する5つのアイテム。Color・Constant・Font・Icon・StyleBoxがUIボタンの見た目を作る
アイテム何を決めるか
Color色(文字色・背景色など)ボタンの文字色、ラベル色
Constant数値(余白・間隔など)コントロール間のスペース
Fontフォント(種類・サイズ)標準フォント、見出しフォント
Iconアイコン画像チェックボックスのチェック
StyleBox最重要。 背景・枠・角丸・影ボタンやパネルの見た目そのもの

これらは「どのノードタイプ(例: Button)の、どのアイテム名(例: font_colornormal)か」の組み合わせで管理されます。中でも StyleBox がデザインの大部分を担う心臓部です。

テーマの継承と優先順位

テーマは、シーンツリーを 上から下へ滝のように流れます(CSSに似ています)。同じ要素に複数の指定があるときは、次の順で優先されます。

テーマの適用優先順位。ノードのオーバーライドが最優先で、ノードのtheme、親のtheme、プロジェクト設定、エディタ標準の順に流れる
  1. ノード固有のオーバーライドadd_theme_*_override())← 最優先
  2. そのノードの theme
  3. 親から継承した theme
  4. プロジェクト設定のデフォルトテーマ
  5. Godotエディタのデフォルト(最後のフォールバック)

理想は、 プロジェクト全体を1つのグローバルテーマで統一し、例外だけを下位で上書きする 流れです。これで「9割はテーマ、1割だけ個別調整」というきれいな設計になります。

Sponsored

StyleBoxFlatでボタンをデザインする

まずはコードなしで、テーマエディタを触ってみましょう。ファイルシステムで右クリック →「新規リソース」→ Theme を作り、main_theme.tres として保存します。これを [プロジェクト設定] → [Gui] → [Theme] → [Custom] に割り当てると、プロジェクト全体のデフォルトテーマになります。

テーマエディタで最も多用するのが StyleBoxFlat です。これ1つで背景色・角丸・枠線・影を設定でき、フラットデザインからマテリアル風まで作れます。

StyleBoxFlatによるボタンの状態別の見た目。normal・hover・pressed・disabledと、設定できる背景色・角丸・枠線・影

Button タイプを追加し、Stylesnormal(通常時)に「新規 StyleBoxFlat」を作って、次を設定します。

  • Bg Color :背景色
  • Corner Radius :四隅の角丸
  • Border Width / Color :枠線の太さと色
  • Shadow :影(立体感を出す)

同じ要領で hover(少し明るく)、pressed(少し暗く)、disabled(薄く)も作ると、状態の変化が自然になります。これで、プロジェクト内の すべての Button が自動的にこのスタイルに揃います

実践:ダークモード切り替えを作る

テーマの真価は、コードから丸ごと差し替えられることです。多くのゲームや設定画面にある ダークモード / ライトモード切り替え を作ってみましょう。RPGでもツール系でも、やることは同じです。

light_theme.tresdark_theme.tres の2つを用意し、切り替えを Autoload のシングルトンに持たせます。

ライトテーマとダークテーマの同じUIが、テーマ差し替えのトグルで一斉に切り替わる図
# settings.gd (Autoloadに登録)
extends Node

const LIGHT_THEME := preload("res://themes/light_theme.tres")
const DARK_THEME := preload("res://themes/dark_theme.tres")

var is_dark := false:
    set(value):
        is_dark = value
        _apply_theme()

func _ready() -> void:
    _apply_theme()

func _apply_theme() -> void:
    # ルート(ビューポート)にテーマを入れると、UI全体へ流れる
    get_tree().root.theme = DARK_THEME if is_dark else LIGHT_THEME

func toggle() -> void:
    is_dark = not is_dark

設定画面のボタンから Settings.toggle() を呼ぶだけで、ゲーム全体のUIが一瞬で切り替わります。ボタンとこの処理をつなぐのは シグナル の出番です。

特定のボタンだけを一時的に目立たせたいときは、テーマ自体はいじらず、そのノードだけを上書きします。ただし 共有リソースを直接書き換えないよう、必ず .duplicate() してから変更します。

func highlight(button: Button) -> void:
    # 共有StyleBoxをそのまま変えると全ボタンに波及する → 複製して変える
    var box := button.get_theme_stylebox("normal").duplicate() as StyleBoxFlat
    box.border_width_bottom = 8
    button.add_theme_stylebox_override("normal", box)
    button.add_theme_font_size_override("font_size", 24)

ポイントは2つです。

  • 全体はテーマ差し替えで一括get_tree().root.theme を入れ替えれば、UI全体が一斉に切り替わります。1ノードずつ直す必要はありません。
  • 例外だけ上書き、必ず複製get_theme_stylebox() の戻り値は共有物です。直接いじると全ボタンに影響するので、.duplicate() した複製を上書きするのが鉄則です。
Sponsored

よくある間違いとベストプラクティス

StyleBoxを直接変更すると全ボタンに波及するが、duplicate()で複製してから変更すれば1つだけ変わる比較図
よくある間違いベストプラクティス
何でも add_theme_*_override() で個別上書きし、継承を無視するベーステーマを定義し、差分だけを下位で上書きする
すべてのスタイルを1つの巨大テーマに詰める「ベース」「ゲームUI」「メニュー」など関心事で 分割 する
get_theme_stylebox() の戻り値を直接変更する必ず .duplicate() してから変更する(共有物への副作用を防ぐ)
テーマを使わず全ノードを個別設定するテーマでUIの9割を定義し、例外だけオーバーライド

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

  • カスタムControlをテーマ対応に :自作UIノードは _notification()NOTIFICATION_THEME_CHANGED を受け、get_theme_color() などで取り直して queue_redraw() すると、テーマ変更に追従します。
  • テーマは分割して組み合わせる :ベーステーマの上に、メニュー用・ゲーム内HUD用のテーマを重ねると管理しやすくなります。
  • 切り替えは preload が有利 :ダーク/ライトのように切り替えるテーマは preload しておくと、代入するだけで軽快に切り替わります。
  • 土台はコンテナ :見た目の前に、配置は Controlノードとレイアウトコンテナ で整えておくと、テーマの効果が活きます。

まとめ

  • Theme :Color / Constant / Font / Icon / StyleBox の5アイテムでUIの見た目を一元管理する
  • 継承 :オーバーライド > ノードのtheme > 親 > プロジェクト > エディタ の順。全体を統一し例外だけ上書き
  • StyleBoxFlat :背景・角丸・枠・影でボタンなどをデザイン。状態(normal / hover / pressed)ごとに用意する
  • 動的切り替えpreload したテーマを get_tree().root.theme に代入すればダークモードも一発。個別上書きは .duplicate() してから

まずはテーマエディタで StyleBoxFlat を1つ作り、Button の見た目を変えるところから始めてみてください。それだけで、UI全体の統一感がぐっと上がります。配置の土台は Controlノードとレイアウトコンテナ と合わせて押さえると、UI作りの基礎が固まります。