UI ToolkitをランタイムUIに導入する前に知っておきたかったこと

## はじめに
私は普段、Webのフロントエンドエンジニアとして働いていますが、Unityを使ったアプリの開発に携わる機会がありました。

初めてUnityのUI Toolkitを使ったのですが、Web開発と似ている部分も多く馴染みやすかった一方で、まだまだ情報が少なく苦労したところもありました。
特に、エディタ拡張向けのコードにたどり着くことが多く、進めた後で「参照方法が違った」と気づくミスもありました。
そこで、自分が調べて役に立ったことを、備忘録としてまとめてみたいと思います。

Unityのバージョンは `Unity6(6000.0)` を使用します。



## UI Toolkitとは？

https://docs.unity3d.com/6000.0/Documentation/Manual/UIElements.html

Unityが提供する最新のUIシステムで、HTMLやCSSと似た仕組みです。
Unity内でのUI構築が簡単にできるのが特徴で、エディター拡張だけでなく、ランタイムのアプリやゲームのUIにも使えます。

主な構成要素

- **UXML**：UIの構造をHTMLやXMLのように書けるマークアップ言語です。UIの構造（Visual Tree）をツリー状に記述します。
- **USS**：CSSのようにUIのスタイルを定義できます。基本的には専用のUSSファイルを使いますが、C#から動的に適用することも可能です。



## どんなプロジェクトに向いている？

Unityは、今後UI Toolkitを標準のUIシステムとして推奨していく方針を発表していますが、2025年3月時点では、uGUIと比べてまだ未対応の機能も多く、用途に応じた使い分けが必要なのが現状です。

以下に、ユースケース別に簡単に比較をまとめました。（[詳細：Comparison of UI systems in Unity](https://docs.unity3d.com/6000.0/Documentation/Manual/UI-system-compare.html)）

|                   | UI Toolkit | uGUI | IMGUI |
|-------------------|------------|------|-------|
| マルチ解像度対応     | ◎          | ○    | ×     |
| スクリーン空間(2D)UI | ◎          | ◎    | ×     |
| ワールド空間(3D)UI   | △          | ◎    | ×     |
| カスタムシェーダー    | ×          | ◎    | ×     |
| エディタ拡張         | ◎          | ×    | ○     |

特に、Webのような画面UIや設定画面、サービス系のアプリUIに特に向いているようです。
逆に、3D空間に浮かぶUIや特殊な描画表現を求めるプロジェクトはuGUIを使ったほうが現時点では良さそうです。



## 知っておくと便利な機能と用語

UI Toolkitを触る上で覚えておくと便利な機能を紹介します。

### UI Builder
UXMLとUSSを編集できる公式のエディタツールで、プレビューを見ながら直感的にUIを作成・調整できます。


1. **StyleSheets**：スタイルシートの追加、並べ替え、削除
1. **Hierarchy**：UIドキュメント（UXML）の要素階層をツリー形式で表示
1. **Library**：利用可能なUI要素を一覧表示
1. **Viewport**：UXMLドキュメントの出力を編集可能なキャンバス上に表示するエリア
1. **UXML Preview / USS Preview**：生成されたUXMLとUSSのコードのプレビュー
1. **Inspector**：選択したUI要素のプロパティやスタイルを詳細に編集

![UIBuilderAnnotatedMainWindow](https://docs.unity3d.com/uploads/Main/UIBuilder/UIBuilderAnnotatedMainWindow.png "UIBuilderAnnotatedMainWindow")
[出典：UIB-interface-overview.html](https://docs.unity3d.com/Manual/UIB-interface-overview.html)

<hr/>

### UXMLとVisual Tree

UXMLは、HTMLのような記述でUIを定義できるマークアップ言語です。UXMLファイルがUIの階層構造（Visual Tree）を形成します。

```html
<!-- example.uxml -->
<engine:UXML xmlns="UnityEngine.UIElements">
    <engine:VisualElement name="root">
        <engine:Box name="sound-settings">
            <engine:Label text="Sound Settings" />
            <engine:Toggle name="mute-all-sounds" text="Mute All Sounds" />
            <engine:Slider name="volume-slider" />
        </Box>
        <engine:Box name="input-settings">
            <engine:Label text="Input Settings" />
            <engine:Toggle name="invert-mouse" text="Invert Mouse" />
        </engine:Box>
    </engine:VisualElement>
</engine:UXML>
```

![VisualTreeExample](https://docs.unity3d.com/uploads/Main/VisualTreeExample.png "VisualTreeExample")
[出典：UIE-VisualTree.html](https://docs.unity3d.com/Manual/UIE-VisualTree.html)

<hr/>

#### USS（Unity Style Sheets）

Web開発のCSSとほぼ同じ感覚で書けるため、スタイルの管理や変更が容易です。
しかし、細かいところではCSSと一部異なるので、[USS common properties](https://docs.unity3d.com/6000.0/Documentation/Manual/UIE-USS-SupportedProperties.html)を確認してみてください。

```css
selector {
  property1: value;
  property2: value;
}
```
##### USS のベストプラクティス
- インラインスタイルはメモリ負荷が高くなるため、USSファイルを使用する
- 複雑なセレクターはパフォーマンスを低下させるため、シンプルなセレクターを心がける
- :hover を深い階層のUIに適用すると処理負荷が増すため、できるだけ避ける
- 要素のクラス数が増えるとスタイル適用の処理コストが増すため、クラス数を最適化する
- BEMを活用すると、統一されたクラス名でスタイル管理がしやすい

[詳細：UIE-USS-WritingStyleSheets.html](https://docs.unity3d.com/6000.0/Documentation/Manual/UIE-USS-WritingStyleSheets.html)

<hr/>

#### 疑似クラス

マウスホバーやクリックなど、簡単なインタラクションはUSSの疑似クラスで手軽に実現できます。

```css
/** ホバー時の背景色変更 **/
.button-primary:hover {
  background-color: #0056b3;
}
```

<hr/>

#### UQuery

Visual Treeの中で、CSSセレクターのように簡単に特定のUI要素を見つけられます。

```C#
// C#での利用例
var container = rootVisualElement.Q<VisualElement>("container");
var button = rootVisualElement.Q<Button>(className: "button-primary");
```

<hr/>

#### Manipulator

クリックやドラッグなどのユーザー操作を簡単に実装・管理できます。

```C#
public class DragManipulator : PointerManipulator
{
    protected override void RegisterCallbacksOnTarget()
    {
        target.RegisterCallback<PointerDownEvent>(OnPointerDown);
        target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
        target.RegisterCallback<PointerUpEvent>(OnPointerUp);
    }

    protected override void UnregisterCallbacksFromTarget()
    {
        target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
        target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
        target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
    }

    private void OnPointerDown(PointerDownEvent evt)
    {
        Debug.Log("ドラッグ開始");
    }

    private void OnPointerMove(PointerMoveEvent evt)
    {
        Debug.Log("ドラッグ中");
    }

    private void OnPointerUp(PointerUpEvent evt)
    {
        Debug.Log("ドラッグ終了");
    }
}
```

<hr/>

#### Custom Controls

再利用可能なUI部品を作れます。何度も同じUI要素を作る際に便利です。

```C#
[UxmlElement("CustomButton")] 

public partial class CustomButton : Button {  
  public CustomButton() {
    text = "Custom Button";
  }
}
```

```html
<!-- UXMLでカスタムボタンを利用する -->
<engine:UXML xmlns="UnityEngine.UIElements">
    <engine:CustomButton />
</engine:UXML>
```

:::note warn
UxmlElement属性はUnity2023.2以降で導入された機能で、古い記事を参考にする際は、UxmlFactoryとしてコード例が載っていることがあるので注意してください。
:::

<hr/>

### Data Binding

スクリプトのプロパティとUI要素を同期させる仕組みで、値が変更された際にイベントハンドラーを書く必要がなくなります。

![runtime-binding-get-started](https://docs.unity3d.com/uploads/Main/uitk/runtime-binding-get-started.png "runtime-binding-get-started")
[出典：UIE-get-started-runtime-binding.html](https://docs.unity3d.com/Manual/UIE-get-started-runtime-binding.html)

#### Data Bindingのメリットと注意点

**メリット**
- **シンプルな同期**：プロパティの変更が自動でUIに反映される
- **コードの簡略化**：イベント処理が不要になり、コードがスッキリする
- **保守性の向上**：UIとロジックが分離され、メンテナンスがしやすくなる

**注意点（2025年3月現在）**
- すべてのプロパティに対応しているわけではない
- 頻繁な更新や大量のプロパティを使用すると、パフォーマンスが低下する可能性がある
- 公式情報や実践例がまだ少なく、問題解決が難しい場合がある

<hr/>

### UI Toolkit Debugger
UI要素の構造やスタイルをリアルタイムで確認でき、スタイルが思った通りに適用されない時に役立ちます。

![ui-debugger](https://docs.unity3d.com/uploads/Main/uitk/ui-debugger.png "ui-debugger")
[出典：UIE-ui-debugger.html](https://docs.unity3d.com/Manual/UIE-ui-debugger.html)


## サンプルアセット「QuizU」が参考になった

https://assetstore.unity.com/packages/essentials/tutorial-projects/quizu-a-ui-toolkit-sample-268492

Unityが提供する、プログラマー向けのインタラクティブなクイズアプリのサンプルで、UI Toolkitのコンポーネントの連携や、さまざまなデザインパターンの活用方法を学ぶことができます。
実際のゲーム開発に役立つUI設計のテクニックが網羅されており、UI Toolkitを活用した効率的なUI開発のノウハウを習得できる実践的なリソースなので、ぜひ一度チェックしてみてください。

### 学べるポイント

#### イベントの発行と伝搬
- UI Toolkitのイベントシステムを活用し、ボタン押下などのユーザー入力をイベントとして処理
- カスタムイベントを発行し、別のオブジェクトでリッスンする仕組みを実装

#### ステートパターンによる画面遷移管理
- クイズの出題画面・結果画面を状態遷移で管理
- UI Toolkitを使って状態ごとに適切なUIを切り替える方法を解説

#### メニュー画面の管理
- タイトル画面や設定画面などのナビゲーションをUI Toolkitで実装
- 画面の有効・無効切り替えパターンの参考になる

#### MVPパターン
- UI（View）とゲームロジックを分離し、保守性の高い設計を実現
- Viewが入力をPresenterに通知し、Presenterがモデルを操作して反映する流れを学べる

#### その他の実践テクニック
- イベントハンドリングのベストプラクティス（イベント委譲など）
- UIアニメーション（フェードイン・アウトなどの実装）
- USS（スタイルシート）によるテーマ切り替え



## おわりに
UI Toolkitを触って、公式マニュアルをしっかり読むことが大事だと改めて思いました。
公式ドキュメントに情報が載っているのに、つい流し読みで始めてしまうことが多いんですよね...。

また、Unityは2025年2月に[最新のロードマップ](https://discussions.unity.com/t/ui-toolkit-development-status-and-next-milestones-february-2025/1607740)を公開しています。
今後も新機能や改善が続々と予定されていますが、個人的には「キーフレームUIアニメーションの作成とシーケンス制御」の実装に特に期待しています！