Version: 2022.3
言語: 日本語
移行ガイド
IMGUI から UI Toolkit への移行

Unity UI (uGUI) から UI Toolkit への移行

このページでは、uGUI (Unity UI) の使用経験のある開発者が新しい UI Toolkit システムに移行するためのガイドを提供し、uGUI と UI Toolkit の共通点と相違点を説明します。

uGUI はランタイム専用のUIシステムなので、このページではランタイムUIに焦点を当てます。UI Toolkit はランタイムUIとエディタUIの両方を作成できます。このガイドは、UI Toolkit の両方のユースケースに適用されます。

UI 階層

uGUI も UI Toolkit の UI も、階層ツリー構造の中で UI を構築、管理します。uGUI では、この階層内の全ての要素が、個々のゲームオブジェクトとして Hierarchy ビューのパネルに表示されます。UI Toolkit では、ビジュアル要素が ビジュアルツリー 内に整理されます。ビジュアルツリー はパネル内に表示されません。

UI Toolkit での UI 階層の表示とデバッグは、UI デバッガーを使用して行えます。UI デバッガーは、エディターツールバーの Window > UI Toolkit > Debugger の下にあります。

UI デバッガー
UI デバッガー

主な相違点

Canvas と UIDocument

uGUI の Canvas コンポーネントは、UI Toolkit の UIDocument コンポーネントと似ています。どちらもゲームオブジェクトにアタッチする MonoBehaviour です。

uGUI では、Canvas コンポーネントが UI ツリーのルートに位置します。これは Canvas Scaler コンポーネントと連携して、UI のソート順、レンダリング、スケーリングモードを決定します。

UI Toolkit では、UIDocument コンポーネントに PanelSettings オブジェクトへの参照が含まれています。PanelSettings には、スケールモードやソート順などの、UI のレンダリング設定が含まれています。複数の UIDocument コンポーネントが同じ PanelSettings オブジェクトを指すことができるので、同じシーンに複数の UI 画面を使用する場合にパフォーマンスが最適化されます。

Panel Settings
Panel Settings

uGUI では、UI ツリーの階層は、Canvas コンポーネントを持つゲームオブジェクトの下に位置します。UI Toolkit では、UIDocument コンポーネントがビジュアルツリーのルート要素への参照を持ちます。

UIDocument コンポーネントには、(ランタイムにビジュアルツリーが構築される基となる) UI レイアウトを定義する UXML ファイルへの参照も含まれています。詳しくは UI の作成 のセクションを参照してください。

ノート: エディター UI には、UIDocument コンポーネントは必要ありません。EditorWindow からカスタムクラスを派生させた上で CreateGUI() を実装することができます。実用的な例については カスタムエディターウィンドウの作成 を参照してください。

ゲームオブジェクトコンポーネントとビジュアル要素

UI Toolkit では、UI 要素は “コントロール” または “ビジュアル要素” と呼ばれます。UI 要素には、例えば以下のようなものがあります。

  • コントロール
  • ボタン
  • テキストラベル

uGUI はゲームオブジェクトから UI 階層を構築します。新しい UI 要素を追加するには、階層に新しいゲームオブジェクトを追加する必要があります。個々のコントロールは MonoBehaviour コンポーネントとして実装されます。

UI Toolkit では、ビジュアルツリー は仮想的なもので、ゲームオブジェクトを使用しません。Hierarchy ビューでの UI 階層の構築や表示はできなくなりましたが、各 UI 要素にゲームオブジェクトを使用することによるオーバーヘッドが解消されます。

uGUI では、UI 要素は UIBehavior 基本クラスから (直接的または間接的に) 派生します。同様に、UI Toolkit では、全ての UI 要素は VisualElement という基本クラスから派生します。重要な違いは、VisualElement クラスは MonoBehaviour から派生していないことです。ビジュアル要素はゲームオブジェクトにアタッチできません。

スクリプトでの UI Toolkit コントロールの操作は、uGUI コントロールの操作と似ています。 以下の表は、スクリプト使用した、uGUI での UI コントロールとの一般的なインタラクションと、UI Toolkit でそれに相当するインタラクションを示したものです。

アクション uGUI UI Toolkit
ラベルにテキストを書き込む m_Label.text = "My Text"; m_Label.text = "My Text";
トグルの状態を読み取る bool isToggleChecked = m_Toggle.isOn; bool isToggleChecked = m_Toggle.value;
ボタンへのコールバックの割り当て m_Button.onClick.AddListener(MyCallbackFunc); m_Button.clicked += MyCallbackFunc_1;
or
m_Button.RegisterCallback<ClickEvent>(MyCallbackFunc_2);

コントロールとそのプロパティやイベントについての詳細は、コントロールの概要 のページを参照してください。

UI 要素へのアクセス

uGUI では、スクリプトで UI 要素にアクセスする方法は 2 つあります (以下参照)。

  • エディターで UI コンポーネントへの参照を割り当てる
  • GetComponentInChildren<T>() などのヘルパー関数を使用して、階層内でコンポーネントを見つける

UI Toolkit にはゲームオブジェクトやコンポーネントがないため、エディターでコントロールへの参照を直接割り当てることはできません。これらはランタイムにクエリ関数を使用して解決する必要があります。 代わりに、UIDocument コンポーネントを通してビジュアルツリーにアクセスします。

UIDocumentMonoBehaviour なので、参照として割り当ててプレハブの一部にすることができます。UIDocument コンポーネントはルートのビジュアル要素への参照を保持します。uGUI と同様に、スクリプトは、ルートから、タイプや名前によって子要素を見つけることができます。

以下の表は、Unity UI での UI コントロールへのアクセス方法と UI Toolkit での UI コントロールへのアクセス方法を直接比較したものです。

アクション uGUI UI Toolkit
UI 要素を名前で探す transform.FindChild("childName"); rootVisualElement.Query("childName");
UI 要素のタイプ別検索 transform.GetComponentInChildren<Button>(); rootVisualElement.Query<Button>();
エディターでの参照の直接割り当て 不可

UI の作成

uGUI と UI Toolkit の最大の違いの一つは、ユーザーインターフェースの作成です。

uGUI でも UI Toolkit でも、UI を視覚的に構築し、エディターでプレビューすることができます。uGUI では、UI がプレハブ内に保存され、個々の UI コントロールにアタッチされたロジックスクリプトも一緒に保存されます。

UI Toolkit では、UI レイアウトは UI Builder で作成され、1 つまたは複数の UXML ファイルとして保存されます。ランタイムに、UIDocument コンポーネントが、ビジュアルツリーがアセンブルした UXML ファイルをメモリにロードします。

uGUI に似た方法として、スクリプトから直接 UI コントロールを作成し、ランタイムにビジュアルツリーに追加することが可能です。

プレハブ

uGUI では、個々の UI コントロールにゲームオブジェクトを使用し、ビジュアルとロジックの両方を含むプレハブを使用します。UI Toolkit は、ロジックとレイアウトを分離するため、再利用性に対するアプローチが異なります。UXML とカスタムコントロールによって、再利用可能な UI コンポーネントを作成できます。

UI Toolkit でプレハブに類似したテンプレートを作成するには、以下を行ってください。

  1. 部分的な UI 要素のための XML ファイルを作成します。
  2. UIDocument コンポーネントを持つゲームオブジェクトを作成します。
  3. そのゲームオブジェクト内で UXML ファイルを参照します。
  4. 同じゲームオブジェクトに、UI コンポーネントのロジックを処理するスクリプトを追加します。
  5. このゲームオブジェクトをプレハブとして保存します。

UI レイアウト

uGUI では、個々の UI 要素の画面上への配置は手動で行います。デフォルトでは、UI コントロールは自由に動かせ、直接の親からのみ影響を受けます。同じ親の下にある他の UI コントロールは、兄弟の位置やサイズに影響を与えません。要素の位置やサイズはピボットやアンカーで制御されます。

UI Toolkit のレイアウトシステムは、ウェブデザインの影響を受けており、自動レイアウト生成に基づいています。自動レイアウトシステムは、デフォルトで全ての要素に影響し、要素のサイズと位置は、同じ親の下にある他の要素に影響します。

UI Toolkit のデフォルトの動作は、uGUI で VerticalLayoutGroup の中に全ての要素を配置してそれぞれに LayoutElement コンポーネントを追加するのと同等です。

自動レイアウト生成を無効にするには、ビジュアル要素の IStyle position プロパティを変更します。全てのビジュアル要素にこのプロパティがあります。コードサンプルについては ビジュアルツリー を参照してください。

UI Toolkit には、UI 要素のアンカーとピボットに直接相当するものがありません。これは、uGUI とレイアウトの仕組みが根本的に異なるためです。

要素のサイズと位置はレイアウトエンジンによって制御されます。詳細は レイアウトエンジン および 座標と位置のシステム を参照してください。

レンダリングの順番

uGUI では、階層内におけるゲームオブジェクトの順番によってレンダリングの順番が決まります。階層の一番下にあるオブジェクトは、最後にレンダリングされ、一番上に表示されます。複数のキャンバスがあるシーンでは、ルート Canvas コンポーネントの Sort Order が、個々の UI ツリーのレンダリング順を決定します。

UI Toolkit における ビジュアルツリー 内のレンダリング順もこれと同様に処理されます。親要素が子要素の前にレンダリングされ、子要素は 1 番目から先にレンダリングされ、最後の要素が最後にレンダリングされます。つまり、最後が一番上に表示されます。複数の UI ドキュメントがあるシーンでは、レンダリング順序はルート UIDocument コンポーネントの Sort Order 設定によって決まります。

uGUI で要素のレンダリング順を変更する (例えば、ある要素を一番上に表示する) には、ゲームオブジェクトの Transform コンポーネントに Sibling 関数を呼び出します。VisualElement クラスにも、同様にレンダリング順を制御する関数があります。UI Toolkit の全てのコントロールはこのクラスから派生するため、全てのコントロールがこの関数にアクセスできます。

以下の表は、レンダリング順を制御する uGUI 関数と、UI Toolkit でそれに相当する関数を示したものです。

アクション uGUI UI Toolkit
要素を他の兄弟の下にレンダリングする transform.SetAsFirstSibling(); myVisualElement.SendToBack();
要素を他の兄弟の上にレンダリングする transform.SetAsLastSibling(); myVisualElement.BringToFront();
要素の兄弟に対するレンダリング順序を手動で制御する transform.SetSiblingIndex(newIndex); myVisualElement.PlaceBehind(sibling);
myVisualElement.PlaceInFront(sibling);

イベント

uGUI の場合と同様に、UI Toolkit のユーザーインタラクションもイベントをトリガーします。コードは、ボタンを押したりスライダーを動かしたりするようなイベントのコールバックを受け取るためにサブスクライブできます。

uGUI では、全ての UI 要素は MonoBehaviour をベースにしており、エディターでイベントを公開できます。このため、他のゲームオブジェクトの関与するロジックを設定することが可能です。例えば、他の UI 要素を隠したり表示したり、コールバック関数を割り当てたりすることができます。

uGUI の Button の OnClick のインスペクター
uGUI の Button の OnClick のインスペクター

UI Toolkit では、ロジックと UI レイアウトが別々に保存されます。コールバックをゲームオブジェクトに直接設定したり、プレハブに保存することはできなくなりました。全てのコールバックはランタイムで設定し、スクリプティングによって処理する必要があります。

Button playButton = new Button("Play");
playButton.RegisterCallback<ClickEvent>(OnPlayButtonPressed);
...
private void OnPlayButtonPressed(ClickEvent evt)
{
  // Handle button press
}

UI Toolkit のイベントディスパッチシステムは、uGUI のイベントとは異なります。イベントは、その種類によって、対象の UI コントロールだけでなく全ての親コントロールにも送られます。

詳細は イベントのディスパッチ を参照してください。

uGUI と UI Toolkit を同じプロジェクトに使用する

uGUI と UI Toolkit を同じプロジェクトで使用することも可能です。

UI Toolkit は、現在のバージョンでは、3D ワールド空間のピッキングとレンダリングをサポートしていません。ゲームメニュー全体と Network Manager HUD を UI Toolkit で作成し、3D ワールド空間 は uGUI で作成してください。

プロジェクト全体を uGUI で作成し、一部のメニュー項目だけを UI Toolkit で作成することもできます。

それ自体の境界の外で相互作用しない要素には、UI Toolkit と uGUI のどちらでも使用できます。例えば、ランタイム UI の場合、uGUI を使ってオンスクリーンボタン (モバイル用のジョイスティックなど) を作成し、UI Toolkit を使ってモーダルウィンドウを作成することも可能です。

ただし、例えば以下のように、混合した UI 間の高度なインタラクションは機能しません。

  • UI Toolkit でフォーカスされた要素と uGUI で選択されたオブジェクトとの間を、キーボードだけで自由にナビゲートすることはできません。ナビゲートするには、C# スクリプトを使用して境界要素にイベントを登録し、手動で他のドメインから次の要素を選択またはフォーカスする必要があります。
  • UI Toolkit 階層の中に uGUI を埋め込むことや、uGUI 階層の中に UI Toolkit を埋め込むことはできません。RenderTexture を使用して描画することはできますが、イベントが追いつきません。
  • UI Toolkit のスタイルおよびイベント規則は uGUI とは異なります。uGUI と UI Tookit をばらばらに混在させて使用すると、プロジェクトの UI に統一感を持たせることが難しくなります。

その他の参考資料

移行ガイド
IMGUI から UI Toolkit への移行