UI Toolkit には、レイアウトやスタイリングのプロパティに基づいて要素を配置するレイアウトエンジンが搭載されています。レイアウトエンジンは、HTML/CSS のレイアウトシステムである Flexbox のサブセットを実装した Yoga のレイアウト法則を使用しています。
デフォルトでは、すべての要素はレイアウトの一部です。レイアウトには以下のデフォルトの動作があります。
VisualElement
は、サイズ計算でテキストサイズを使用します。この動作は他のレイアウトプロパティによって制限される場合があります。UI Toolkit には、ボタン、トグル、テキストフィールド、などの標準 UI コントロール用のビルトイン コントロール が含まれます。これらのビルトインコントロールには、レイアウトに影響するスタイルがあります。
以下は主なスタイルプロパティです。
flex-direction
in USS): レイアウト方向の 主軸 を指定します。デフォルトは column
で、 主軸 を上から下へ実行します。flex-grow
in USS): 要素が 主軸 方向にどのように展開するかを定義します。これは、同じ親の他の兄弟と共有される比率です。このプロパティは、要素を親のサイズ (兄弟を除く) 全体を占めるように伸ばす場合に便利です。これを行うには、 Flex > Grow の値を 1
に設定します。flex-grow
が 1
に設定された 2 つの兄弟がある場合、それぞれ 主軸 に沿って親の利用可能なサイズの 50% に成長します。align-items
): 交差軸、つまり 主軸 に対して垂直な軸での要素の整列を定義します。例えば、flex-direction: column
と align-items: flex-end
が設定された VisualElement
に 2 つの Button (ボタン) がある場合、2 つの Button はコンテナの右端に押しつぶされます。align-items
のオプションに flex-start
や flex-end
という名前がついているのは、flex-direction
の値に依存しているからです。justify-content
in USS): 主軸 の要素の整列を定義します。例えば、flex-direction: column
と justify-content: flex-end
が設定された VisualElement
に 2 つの Button (ボタン) がある場合、2 つの Button はコンテナの下方の端に押しつぶされます。justify-content
のオプションに flex-start
や flex-end
という名前がついているのは、flex-direction
の値に依存しているからです。詳しくは、フレックスレイアウト を参照してください。
選択した要素に子要素がある場合、UI Builder ではヘッダーのトグルを使って ビューポート のフレックス (flex-) 関連のスタイルプロパティを切り替えることができます。下の画像は #menu
要素で利用可能なオプションです。
スタイルプロパティを使用すると、複雑で動的なレイアウトを作成できます。以下は、画面の右下端に Button
を固定するレイアウトの例です。
このレイアウトの UXML は、各コンテナ VisualElement
に設定されたインラインスタイルを示しており、以下のようになります。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="screen-is-blue" style="flex-grow: 1; justify-content: flex-end; background-color: blue;">
<ui:VisualElement name="toolbar-is-orange" style="align-items: flex-end; background-color: orange;">
<ui:Button text="Button" display-tooltip-when-elided="true" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
コンテナは、その形状がわかるように色付けされています。ネストされた VisualElement
コンテナを使用すると、各要素の位置とサイズを明示的に設定することなく、任意の動的なレイアウトを実現することができます。これにより、レイアウトが動的に保たれ、画面のサイズ変更など、より大きなコンテナのサイズ変更に自動的に調整されます。
UI Builder は Position スタイルプロパティもサポートしています。Position > Absolute (絶対) モードでは、デフォルトの Flexbox ベースのレイアウトエンジンから要素が見えなくなります。これは、まるでスペースを取らないのと同じです。Absolute 位置の要素は、Relative (相対) 位置の兄弟要素の上に表示されます。
Absolute 位置を使用する場合、Position > Left、Top、Right、Bottom のスタイルプロパティを使用して、要素を親の各辺からオフセットしてサイズ調整します。これは、画面上の絶対座標を設定するのではなく、親要素からの相対的なオフセットを設定します。Relative モードを使用して親要素を配置することはできます。Left (左) オフセットと Right (右) オフセットの両方を設定すると、要素の Width (幅) スタイルプロパティは無視され、幅は以下の式でもとめられます。
element-computed-width = parent-width - left-offset - right-offset
Left、Top、Right、Bottom はアンカーとして解釈することもできます。例えば、画面の左下に Button
を固定することができます。
下の UXML はインラインスタイルを表示しています。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement style="flex-grow: 1;">
<ui:VisualElement style="position: absolute; left: 0; bottom: 0;" />
</ui:VisualElement>
</ui:UXML>
位置を決める際に、Left を 0
に設定するのと未設定にするのとでは、違いがあります。
Left を 0 に設定
オフセット 0 を設定することを意味します。Left を設定しない
とオフセットを設定せず、他のスタイルプロパティで要素の幅や高さを定義します。これらのオフセットスタイルプロパティは、要素の青い選択境界線の各エッジとコーナーにある追加のサイズ変更ハンドルを介して、 Canvas で直接変更することも可能です。設定されているものと設定されていないものを区別することが重要です。そのため、Canvas には、要素の各辺にオレンジ色の四角形で “アンカー” トグルが表示されています。Canvas のハンドルは、どの “アンカー” が設定されているかによって、要素のサイズを視覚的に変更するときにどのスタイルプロパティを設定するかを調整します。例えば、Canvas の要素をその右枠のハンドルでサイズ変更しているとします。
UI Toolkit のビルトインレイアウトエンジンを回避するので、通常、Absolute 位置モードの使用は推奨されません。また、全体的なレイアウトを変更すると、個々の要素を手動で更新する必要があり、メンテナンスに手間のかかる UI になる可能性があります。しかし、Absolute 位置モードの正当な使用例の 1 つはオーバーレイです。ポップアップやドロップダウンなど、複雑な UI を他の複雑な UI の上にオーバーレイするのに便利です。オーバーレイコンテナ自体にのみ Absolute 位置を使用し、オーバーレイ内部では Relative モードを使用することができます。以下は、単純な中央寄せポップアップの例です。
そして、参考までに UXML を以下に示します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="complex-ui-screen">
<ui:Toggle label="Toggle" />
<ui:MinMaxSlider picking-mode="Ignore" label="Min/Max Slider" min-value="10" max-value="12" low-limit="-10" high-limit="40" />
<ui:Label text="Label" />
<ui:Button text="Button" />
<ui:Button text="Button" />
</ui:VisualElement>
<ui:VisualElement name="overlay" style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.71); align-items: center; justify-content: center;">
<ui:VisualElement name="popup" style="background-color: rgba(70, 70, 70, 255);">
<ui:Label text="Exit?" name="message" />
<ui:Button text="Ok" name="ok-button" style="width: 108.3333px;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
上の例では、Absolute 位置の使い方を強調しています。すべての Position > Left、Top、Right、Bottom を 0
に設定します。つまり、画面の端から 0
ピクセル離れた位置になります。これにより、#overlay
要素は、#complex-ui-screen
コンテナ要素に重なるようになります。また、#overlay
要素に半透明の背景を設定すると、他の UI が暗く表示されるようになります。#overlay
を使用して、Relative 位置を設定し、#popup
コンテナ VisualElement
を中央に配置します。
以下のリストは、レイアウトエンジンのパフォーマンスを向上させるためのコツです。
要素のサイズを定義するには、width
と height
を設定します。
要素に調整できるサイズを割り当てるには、flexGrow
プロパティ (USS: flex-grow: <value>;
) を使用します。flexGrow
プロパティの値は、その兄弟によって決定されるときに、基本ウェイトを要素のサイズに割り当てます。
水平レイアウトに切り替えるには、flexDirection
プロパティを row
(USS: flex-direction: row;
) に設定します。
元のレイアウト位置に基づいて要素をオフセットするには、相対位置を使用します。
要素を親位置の矩形に対して相対的に配置するには、position
プロパティを absolute
に設定します。この場合、兄弟や親のレイアウトには影響しません。