Unity

【UI Toolkit】でスタミナゲージを作る

1. はじめに

前回の記事では、UI Toolkitを使ってソーシャルゲーム風のホーム画面UIを作成しました。
画面レイアウトやメニュー配置は形にできましたが、スタミナゲージのような「進捗バー系UI」は簡易的な見た目に留めていました。

今回の記事では、スタミナゲージUIをより実用的かつ見栄え良く作り込む方法をご紹介します。
UI Toolkit(UXML・USS)を活用し、コードベースではなくUIビルダーとスタイル指定のみで再現性の高いUIパーツを実装することを目的とします。

この記事で扱う内容

  • UI Toolkitで「枠付きゲージUI」の実装方法
  • USSでのborder・radius・overflowの活用
  • 実際のゲームUIに近い「Fillゲージ」の表現

完成するスタミナゲージは、以下のようなものです。

このアプローチはスタミナゲージだけでなく、経験値バーやスキルゲージなど、他のUIパーツにも応用できます。
UI Toolkitで独自デザインのUIを作りたい方の参考になれば幸いです。

UI Toolkitについてはこちら

ホーム画面の作り方はこちら

2. UI ToolkitでゲージUIを作る考え方

今回作成するスタミナゲージは、次の5つのパーツで構成します

パーツ名役割
エリア(area)表示するエリア
(wrapper)白いボーダーの枠
ゲージ背景(bg)黒い部分
ゲージ本体(fill)オレンジの変動する部分
スタミナ数値ラベル(label)真ん中のテキスト

これをUI ToolkitのVisualElementとUSSで組み合わせます。

3. UXMLの作成

以下のUXMLを作成します

図解としてはこんな感じです
TopBar前回作成
├─ icon-area前回作成

└─ stamina-areaスタミナUI全体
    ├─ stamina-bar-wrapperゲージの枠
    │   └─ stamina-bar-bgゲージ背景
    │       └─ stamina-bar-fillスタミナ残量の本体
    └─ stamina-labelスタミナ数値の表示

<engine:VisualElement name="stamina-area" class="stamina-area">
    <engine:VisualElement name="stamina-bar-wrapper" class="stamina-bar-wrapper">
        <engine:VisualElement name="stamina-bar-bg" class="stamina-bar-bg">
            <engine:VisualElement name="stamina-bar-fill" class="stamina-bar-fill" />
        </engine:VisualElement>
    </engine:VisualElement>
    <engine:Label name="stamina-label" text="22/100" class="stamina-label" />
</engine:VisualElement>

4. USSでスタイルを設定する

4.1 stamina-area

stamina-areaは、スタミナゲージ全体(バーとラベル)をまとめるコンテナです。
主に「トップバー内のどこにスタミナUIを配置するか」を決める役割があります。
この中に「ゲージ本体」と「数値ラベル」の2つを配置します。

.stamina-area {
    width: 30%;
    height: 50%;
    flex-direction: column;
    justify-content: center;
    position: relative;
}

widthとheightで表示するエリアのサイズを決めます。
横幅はTopBarの30%の分、縦幅はTopBarの50%になっています。

4.2 stamina-bar-wrapper

stamina-bar-wrapper は スタミナゲージの外枠を担うVisualElementです。
この要素は主に以下の役割を持っています。

  • ゲージ全体のサイズを決める
    親要素 stamina-area 内で ゲージの横幅・高さを100%に広げ、見た目の「枠」の大きさを決めます。
  • ゲージ枠線の色・太さ・角丸を設定する
    border-width、border-color、border-radius を使って、
    視認性の高い白い太線柔らかい角丸のデザインを作ります。
    これにより「ゲージエリアの存在感」が強調され、プレイヤーがすぐ視認できるUIになります。
  • ゲージ本体(背景・残量)の土台になる
    背景(stamina-bar-bg) と 残量バー(stamina-bar-fill) はこの中に配置されます。
    align-items: stretch によって中身は枠いっぱいに広がり、枠線とのバランスが保たれます。

UIとしては「ただの飾り」ではなく、枠があることでゲージの情報量と視認性が高まるのがポイントです。

.stamina-bar-wrapper {
    border: 10px;
    width: 100%;
    height: 100%;
    align-items: stretch;
    border-left-color: rgb(255, 255, 255);
    border-right-color: rgb(255, 255, 255);
    border-top-color: rgb(255, 255, 255);
    border-bottom-color: rgb(255, 255, 255);
    border-top-left-radius: 24px;
    border-top-right-radius: 24px;
    border-bottom-right-radius: 24px;
    border-bottom-left-radius: 24px;
    border-top-width: 10px;
    border-right-width: 10px;
    border-bottom-width: 10px;
    border-left-width: 10px;
}

👆 「え? border指定がこんなに多いの?」 と思った方も多いかもしれません。
これはUI Toolkitならではの仕様によるものです。

📘 なぜUI Toolkitでは冗長なスタイル指定が必要なのか?

UI ToolkitのUSS(Unity Style Sheets)はCSSに似ていますが、CSSそのものではありません
特に「border」や「border-radius」に関する仕様は以下のような特徴があります。

ショートハンド(省略記法)が使えない

WebのCSSならば

border: 10px solid white;
border-radius: 24px;

のように「まとめて一行」で書けます。
しかしUI ToolkitのUSSは borderborder-radius のショートハンドが使えず、
上下左右・四隅ごとに明示的に指定しなければならない 仕様です。

その結果:

border-top-width: 10px;
border-bottom-width: 10px;
border-left-width: 10px;
border-right-width: 10px;

border-top-left-radius: 24px;
border-top-right-radius: 24px;
border-bottom-right-radius: 24px;
border-bottom-left-radius: 24px;

border-colorも同様です。

理由は「UI Toolkitは内部的にborderプロパティを完全分離して管理しているため」であり、
styleシリアライズ時に省略表現を許さない設計思想が背景にあります。

UIビルダー経由だと特にこの形になる

UIビルダー(Unityのビジュアルエディタ)でプロパティを設定すると、
裏で生成されるUSSは必ず「各プロパティごとのフル指定」になります。
これが「UI Toolkitは頭のおかしいセレクタになる」と感じる原因です。
(実際には冗長だけど挙動が安定する設計
でもあります)

このようにして「UI ToolkitはWebのCSSとは別物」という前提を理解した上で、
各要素のスタイルを整えていきます。
続いてはスタミナゲージの「中身部分(背景とゲージ)」を作成します。

4.3 stamina-bar-bg

続いて、ゲージの背景の役割を担う stamina-bar-bg の設定に進みます。

この要素は、枠線の内側に配置される背景として、ゲージのベース部分と「減ったときの背景色」の役割を持ちます。

ポイントは stamina-bar-wrapper の枠に合わせた border-radius の数値にすることです。枠と背景の角丸が揃うことで、隙間や不自然な段差のない美しいゲージになります。

丁度良い数値を見つけて設定しましょう。

.stamina-bar-bg {
    background-color: rgb(30, 30, 30);
    overflow: hidden;
    width: 100%;
    height: 100%;
    border-top-left-radius: 14px;
    border-top-right-radius: 14px;
    border-bottom-right-radius: 14px;
    border-bottom-left-radius: 14px;
}

注意: border-radius の数値が小さすぎたり大きすぎると、
枠と背景の間に「隙間」や「はみ出し」が発生し、不格好な見た目になります。

失敗例

overflow: hidden;

このとき もう1つ重要な設定overflow: hidden; です。
これは 背景エリア(stamina-bar-bg)の内側にあるゲージ本体(stamina-bar-fill)が、角丸の範囲を超えてはみ出さないように切り取る役割 があります。

この設定を加えることで、ゲージの端が背景の角丸にぴったり沿い、自然で滑らかな見た目になります。
マスクのような効果と考えるとわかりやすいでしょう。

4.4 stamina-bar-fill

続いて、スタミナゲージの本体部分である stamina-bar-fill の設定に進みます。

この要素は 「現在のスタミナ量を視覚的に表す部分」です。
実際にスタミナが増減したとき、このバーの 横幅 (width) を変化させることで残量を表現します。

ポイントは、背景 (stamina-bar-bg) 全体を覆う形で左から右に伸び縮みするように作ることです。
また、色やグラデーションのデザインもこの要素で設定し、
「今どれくらいスタミナがあるか」を直感的に分かりやすく伝える役割を担います。

.stamina-bar-fill {
    height: 100%;
    width: 50%;
    background-color: rgb(255, 100, 0);
}

4.5 stamina-label

続いて、スタミナの数値を表示する stamina-label の設定に進みます。
この要素は 「現在のスタミナ値を文字で分かりやすく伝える」 役割を担います。

ゲージだけでは正確な数値が分かりにくいため、「50/100」 のような具体的な数値を表示することで、ユーザーの判断を助けます。

ポイントは position: absolute; を使い、ゲージ本体 (stamina-area) の中央に重ねて表示することです。これにより背景のゲージと数値が視覚的に重なり、コンパクトで見やすいUIになります。

また、フォントはプロジェクトにインポートしたものを指定しましょう。

日本語対応やデザインの統一感を意識するなら、Noto Sansなど読みやすいフォントがオススメです。

.stamina-label {
    color: white;
    font-size: 38px;
    -unity-font-style: bold;
    text-align: center;
    -unity-font-definition: url("インポートしたフォントのURL");
    position: absolute;
    align-self: center;
}

補足: align-self: center; で中央寄せにしつつ、フォントサイズや色も背景と十分なコントラストが出るよう調整すると読みやすくなります。

5. スタミナ量をコードで制御する

ここまででゲージの見た目が完成したので、続いて C#スクリプトからゲージ量を動的に変更する方法 を解説します。

まず、UXML上で作成した
stamina-bar-fill(ゲージ本体)と stamina-label(数値ラベル)をスクリプトから取得します。

VisualElement staminaFill = root.Q<VisualElement>("stamina-bar-fill");
Label staminaLabel = root.Q<Label>("stamina-label");

その後、UpdateStamina 関数を用意し、「現在値」と「最大値」からスタミナの割合を計算してゲージと数値を更新します。

void UpdateStamina(int current, int max)
{
    float percent = (float)current / max * 100f;
    staminaFill.style.width = new Length(percent, LengthUnit.Percent);
    staminaLabel.text = $"{current}/{max}";
}

コードのポイント

  • (float)current / max * 100f;
     現在値を最大値で割って「パーセンテージ(%)」を計算します。
     例: 50 / 100 → 0.5 → 50%
  • staminaFill.style.width = new Length(percent, LengthUnit.Percent);
     ゲージ本体の幅をパーセンテージで設定します。
     CSSと同様に「親要素(背景)」の幅を基準に%で制御できるため、見た目と動作が一致します。
  • staminaLabel.text = $”{current}/{max}”;
     現在値と最大値を「数値ラベル」に反映します。
     例: 50/100

この関数をゲーム内のスタミナ増減処理から呼び出せば、
リアルタイムでゲージ量と数値が同期して動くUIが完成します。

動作テスト

スペースキーを押したらスタミナが5減り、1秒経ったら1回復するというプログラムを組みました。

using UnityEngine;
using UnityEngine.UIElements;

public class StaminaController : MonoBehaviour
{
    public int maxStamina = 100;
    private int currentStamina;

    private VisualElement staminaFill;
    private Label staminaLabel;

    private float recoveryTimer = 0f;
    public float recoveryInterval = 1f;

    void Start()
    {
        // 初期化
        currentStamina = maxStamina;

        var root = GetComponent<UIDocument>().rootVisualElement;
        staminaFill = root.Q<VisualElement>("stamina-bar-fill");
        staminaLabel = root.Q<Label>("stamina-label");

        UpdateStaminaUI();
    }

    void Update()
    {
        // スペースキーで5消費
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ConsumeStamina(5);
        }

        // 経過時間で1回復
        recoveryTimer += Time.deltaTime;
        if (recoveryTimer >= recoveryInterval)
        {
            RecoverStamina(1);
            recoveryTimer = 0f;
        }
    }

    void ConsumeStamina(int amount)
    {
        currentStamina = Mathf.Max(currentStamina - amount, 0);
        UpdateStaminaUI();
    }

    void RecoverStamina(int amount)
    {
        currentStamina = Mathf.Min(currentStamina + amount, maxStamina);
        UpdateStaminaUI();
    }

    void UpdateStaminaUI()
    {
        float percent = (float)currentStamina / maxStamina * 100f;
        staminaFill.style.width = new Length(percent, LengthUnit.Percent);
        staminaLabel.text = $"{currentStamina}/{maxStamina}";
    }
}

コードのポイント

  • スペースキー検知: Input.GetKeyDown(KeyCode.Space)
     → 1回押すごとに5消費
  • 自動回復: recoveryTimer += Time.deltaTime;
     → 60秒経過したら1回復 & タイマーリセット
  • 範囲制限: Mathf.Max, Mathf.Min
     → スタミナは0〜最大値の間に制限

実行

作成したスクリプトをプロジェクトのUIDocumentにセットして実行します。

まとめ

今回は UI Toolkit を使い、枠・背景・ゲージ・ラベルの4つの要素から構成されるソーシャルゲーム風のスタミナゲージを作成し、C#コードからゲージ量を制御する方法を解説しました。
UI要素の構造設計(wrapper・bg・fill・label)や、CSSでの border-radius・overflow の調整ポイントを押さえることで、見た目と挙動が自然なゲージ表現を実現できます。
今回紹介した手法は、スタミナゲージだけでなく「経験値バー」や「HPバー」などにも応用できそうです。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です