Version: 2021.3
言語: 日本語
ランタイム UI の作成
レイアウトエンジン

ビジュアルツリー

UI Toolkit の最も基本的な構成要素は、ビジュアル要素です。ビジュアル要素は、親子関係を持つ階層ツリーに整列されます。下図は、階層ツリーの簡略化された例と、UI Toolkit での描画結果を示しています。

ビジュアルツリーの簡易化された階層構造
ビジュアルツリーの簡易化された階層構造

ビジュアル要素

The VisualElement class is the base for all nodes in the visual tree. The VisualElement base class contains properties such as styles, layout data, and event handlers. Visual elements can have children and descendant visual elements. For example, in the diagram above, the first Box visual element has three child visual elements: Label, Checkbox, and Slider.

スタイルシートを使って、ビジュアル要素の外観をカスタマイズできます。また、イベントコールバックを使ってビジュアル要素の動作を変更することもできます。

VisualElement は、コントロールなどの追加の動作や機能を定義するサブクラスに派生します。UI Toolkit には、特殊な動作をするさまざまなビルトインのコントロールが含まれています。例えば、以下のようなものがビルトインコントロールとして用意されています。

  • ボタン
  • トグル
  • テキスト入力フィールド

また、ビジュアル要素を組み合わせ、その動作を変更することで、カスタムのコントロールを作成することができます。ビルトインコントロールのリストは、コントロールのリファレンス ページを参照してください。

パネル

The panel is the parent object of the visual tree. A visual tree must connect to a panel for the visual elements inside a tree to render. All panels belong to either an Editor Window or a runtime UIDocument. The panel also handles focus control and the event dispatching for the visual tree.

ビジュアルツリーの全ての要素は、ビジュアルツリーを保持するパネルへの直接の参照を保持しています。VisualElement のパネルとの接続を確認するには、この要素の panel プロパティをテストします。ビジュアル要素が接続されていない場合、テストは null を返します。

描画順

ビジュアルツリー内の要素の描画順序は、深さ優先検索に従います。子のビジュアル要素は親要素の上に重ねて表示されます。また、UI Toolkit は、兄弟リストの順に子を描画します。描画順序は以下の通りです。

  1. 一番上のビジュアル要素
  2. そのビジュアル要素の最初の子要素
  3. 子孫の要素の子要素

下の図は、上の例の描画順序を示しています。

ビジュアル要素の描画順序
ビジュアル要素の描画順序

ビジュアル要素の描画順序を変更するには、以下の機能を使用します。

兄弟姉妹のビジュアル要素に関しては、以下を使用します。

座標と位置システム

UI Toolkit uses a powerful layout system that automatically calculates the position and size of individual elements based on the layout parameters in their style properties. This is based on Flexbox, a web layout model. For more information, see Layout Engine.

UI Toolkit には 2 種類の座標があります。

  • Relative: Coordinates relative to the element’s calculated position. The layout system calculates the position of the element, then adds the coordinates as an offset. Child elements can influence the position and size of the parent element, as the layout engine takes them into account when it calculates the element position.
  • Absolute: 親要素に相対的な座標です。これにより、自動的なレイアウト計算は回避し、要素の位置を直接設定します。同じ親の下にある子要素は、要素の位置に影響を与えません。同様に、同じ親の下にある他の兄弟の位置やサイズにも影響を与えません。

各ビジュアル要素は、その位置を計算するために使用する座標系を決定します。どの座標系を使用するかは、要素のスタイルシートで設定できます。

以下のコードは、コードを使ってビジュアル要素の座標空間と位置を設定する方法を示しています。

    var newElement = new VisualElement();
        newElement.style.position = Position.Relative;
        newElement.style.left = 15;
        newElement.style.top = 35;

要素の原点は左上の角です。

レイアウトシステムは、各要素の VisualElement.layoutプロパティ (タイプ Rect) を計算します。これには要素の最終的な位置が含まれます。要素の相対位置または絶対位置が考慮されます。

layout.position は親の座標空間に相対的に、ポイントで表されます。

VisualElement には、要素の位置と回転に追加のローカルオフセットを加えるために使用するトランスフォームプロパティ (ITransform) があります。このオフセットは、計算されたレイアウトプロパティでは示されません。デフォルトでは、transform は同一です。

worldBound プロパティを使用して、レイアウト位置とトランスフォームの両方を考慮に入れて VisualElement の最終的なウィンドウ空間座標を取得します。この位置には、ウィンドウのヘッダーの高さが含まれます。

以下のコードサンプルでは、相対位置と絶対位置の違いを示しています。自動レイアウトシステムを使って、ウィンドウにボックスを加え、その位置を計算しています。あるボックスは、相対的なオフセットの 25 px、別のボックスは、絶対的な位置の 25 px, 25 px を示しています。

ビジュアル要素の配置
ビジュアル要素の配置

この例を実際に見るには、以下を行います。

  1. Under Assets > Scripts > Editor, create a C# script called PositioningTestWindow.
  2. 以下のコードを C# スクリプトにコピーします。
  3. エディターツールバーから、 Window > UI Toolkit > Positioning Test Window を選択します。

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class PositioningTestWindow : EditorWindow
{
    [MenuItem("Window/UI Toolkit/Positioning Test Window")]
    public static void ShowExample()
    {
        var wnd = GetWindow<PositioningTestWindow>();
        wnd.titleContent = new GUIContent("Positioning Test Window");
    }

    public void CreateGUI()
    {
        for (int i = 0; i < 2; i++)
        {
            var temp = new VisualElement();
            temp.style.width = 70;
            temp.style.height = 70;
            temp.style.marginBottom = 2;
            temp.style.backgroundColor = Color.gray;
            rootVisualElement.Add(temp);
        }

        // Relative positioning
        var relative = new Label("Relative\nPos\n25, 0");
        relative.style.width = 70;
        relative.style.height = 70;
        relative.style.left = 25;
        relative.style.marginBottom = 2;
        relative.style.backgroundColor = new Color(0.2165094f, 0, 0.254717f);
        rootVisualElement.Add(relative);

        for (int i = 0; i < 2; i++)
        {
            var temp = new VisualElement();
            temp.style.width = 70;
            temp.style.height = 70;
            temp.style.marginBottom = 2;
            temp.style.backgroundColor = Color.gray;
            rootVisualElement.Add(temp);
        }

        // Absolute positioning
        var absolutePositionElement = new Label("Absolute\nPos\n25, 25");
        absolutePositionElement.style.position = Position.Absolute;
        absolutePositionElement.style.top = 25;
        absolutePositionElement.style.left = 25;
        absolutePositionElement.style.width = 70;
        absolutePositionElement.style.height = 70;
        absolutePositionElement.style.backgroundColor = Color.black;
        rootVisualElement.Add(absolutePositionElement);
    }
}

座標系間の変換

VisualElement.layout.positionVisualElement.layout.transform プロパティはローカル座標系と親座標系間の変換方法を定義します。

VisualElementExtensions 静的クラスでは、座標系間で点や矩形を変換する以下の拡張メソッドを提供します。

  • WorldToLocal は、Panel 空間の Vector2 または Rect を要素内の参照に変換します。
  • LocalToWorldVector2 または RectPanel 空間参照に変換します。
  • ChangeCoordinatesTo は要素のローカル空間の Vector2 または Rect を別の要素のローカル空間に変換します。
ランタイム UI の作成
レイアウトエンジン