Version: 2023.2
言語: 日本語
UXML にスタイルを加える
UXML から他のファイルを参照する

UXML ファイルの再利用

テンプレートとして UXML ファイルを作成し、他の UXML ファイル内でそれを再利用できます。

UXML テンプレートのインポート

大規模なユーザーインターフェースを設計する場合は、UI の部分部分を定義するテンプレート UXML ファイルを作成し、<Template> および <Instance> 要素を使用して、それを別の UXML ファイルにインポートすることが可能です。

例えば、画像、名前、ラベルを持つポートレート UI 要素がある場合、以下の内容で、Assets/Portrait.uxml として UXML テンプレートファイルを作成できます。

<ui:UXML ...>
    <ui:VisualElement class="portrait">
        <ui:Image name="portaitImage" style="--unity-image: url(\"a.png\")"/>
        <ui:Label name="nameLabel" text="Name"/>
        <ui:Label name="levelLabel" text="42"/>
    </ui:VisualElement>
</ui:UXML>

その上で、この Portrait テンプレートを以下のように再利用できます。

<ui:UXML ...>
    <ui:Template src="/Assets/Portrait.uxml" name="Portrait"/>
    <ui:VisualElement name="players">
        <ui:Instance template="Portrait" name="player1"/>
        <ui:Instance template="Portrait" name="player2"/>
    </ui:VisualElement>
</ui:UXML>

UXML 属性のオーバーライド

UXML テンプレートのインスタンスを作成したら、その要素のデフォルト属性値をオーバーライドできます。属性をオーバーライドすれば、同じテンプレートを 、(インスタンスごとに異なる値を使って) 何度もインスタンス化することができます。

属性のオーバーライド

UXML タグで属性をオーバライドできます。属性をオーバーライドするには、以下を指定します。

  • オーバーライドしたい属性を持つ要素の element-name 属性
  • オーバーライドする属性の名前
  • 新しい属性値

例えば、ゲーム内の各プレイヤーに同じ一式の情報を表示したい場合は、UXML テンプレートを作成し、属性のオーバーライドを使用してプレイヤーごとのインスタンスを作成できます。

まず、以下の内容で、テンプレート (例えば MyTemplate.uxml など) を作成します。

<UXML xmlns="Unityui.UIElements">
    <Label name="player-name-label" text="default name" />
    <Label name="player-score-label" text="default score" />
</UXML>

次に、これを別の UXML ファイルからインスタンス化し、各プレイヤーの名前とスコアを表示するために、属性をオーバーライドします。

<UXML xmlns="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
    <Template src="MyTemplate.uxml" name="MyTemplate" />
    <Instance name="player1" template="MyTemplate">
        <!-- Alice is the new value of the text attribute for the player-name-label -->
        <AttributeOverrides element-name="player-name-label" text="Alice" /> 
        <!-- 2 is the new value of the text attribute for the player-score-label -->
        <AttributeOverrides element-name="player-score-label" text="2" />
    </Instance>
    <Instance name="player2" template="MyTemplate">
        <!-- Bob is the new value of the text attribute for the player-name-label -->
        <AttributeOverrides element-name="player-name-label" text="Bob" />
        <!-- 1 is the new value of the text attribute for the player-score-label -->
        <AttributeOverrides element-name="player-score-label" text="1" />
    </Instance>
</UXML>

複数の属性のオーバーライド

各オーバーライドで複数の属性を指定できます。例えば、以下の構文は、player-name-label という名前のインスタンスの全ての要素を検出します。

  • text 属性のデフォルト値を、新しい値 Alice でオーバーライドします。
  • tooltip 属性のデフォルト値を、新しい値 Tooltip 1 でオーバーライドします。
<AttributeOverrides element-name="player-name-label" text="Alice" tooltip="Tooltip 1" />

属性のオーバーライドのネスト

属性のオーバーライドは、要素の階層のネスト状のテンプレートを通して伝播します。例えば、テンプレート A がテンプレート B をインスタンス化し、テンプレート B がテンプレート C をインスタンス化する場合、テンプレート A とテンプレート B の両方がテンプレート C の属性をオーバーライドできます。

When you override attributes in nested templates, the shallowest override takes precedence. In the example above, if template A and template B both override the same attribute of template C, the override in template A determines what actually appears in the rendered UI.

テンプレートインスタンスのスタイルのオーバーライド

UXML テンプレートのインスタンスを作成していて、テンプレート内の要素に style 属性で定義されたインラインスタイルがある場合、その style 属性は、AttributeOverrides を使用してオーバライドすることはできません。ただし、USS スタイルシート内で USS セレクターを使用することで、テンプレートインスタンスのスタイル設定をオーバーライドできます。

例えば、以下のように、Hotkeys.uxml という UXML テンプレートが、2 つのラベルを持つ #Container を定義し、この #Container が、伸縮する行の方向を定義するインラインスタイルを持っているとします。

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <ui:VisualElement name="Container" style="flex-direction: row;">
        <ui:Label text="E" name="Hotkeys" />
        <ui:Label text="Talk" name="Action" />
    </ui:VisualElement>
</ui:UXML>

2 つのテンプレートインスタンスを作成して、2 つ目のインスタンスの伸縮する行の方向を逆にしたい場合、AttributeOverides を使用して 2 つ目のインスタンスの #Container 要素の style 属性をオーバーライドすることはできません。

スタイルをオーバーライドするには、以下のようにします。

  • 上記の UXML テンプレート (Hotkeys.uxml) 内で #Container のスタイルを削除します。
  • UXML インスタンスファイル内で、2 つのインスタンスに名前を付けます (例: HotkeysXMLReversedHotkeysXML など)。
  • ContextHotkeys.uss などの USS スタイルシートを UXML インスタンスファイルに適用します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
    <ui:Template name="HotkeysXML" src="HotkeysXML.uxml"/>
    <Style src="ContextHotKeys.uss"/>
    <ui:Instance template="HotkeysXML" name="HotkeysXML" />
    <ui:Instance template="HotkeysXML" name="ReversedHotkeysXML" />
</ui:UXML>

上記を行った上で、以下のように、ContextHotkeys.uss を作成してテンプレートインスタンス名に応じて #Container のスタイルを変更できます。

# ReversedHotkeysXML > #Container {
    flex-direction: row-reverse;
}
 
# HotkeysXML > #Container {
    flex-direction: row;
}

制限

属性のオーバーライドには以下の制限があります。

  • 属性のオーバーライドは、指定された要素名に従って、一致する属性を見つけます。USS セレクターUQUery を使用して要素を照合することはできません。
  • 要素の binding-path 属性をオーバーライドすることはできますが、データバインディングは属性のオーバーライドには機能しません。
  • 要素の class 属性や name 属性、style 属性はオーバーライドできません。

UXML テンプレート内で子要素をネストする場所を指定する

ビジュアル要素の content-container 属性を使用して、UXML テンプレート内のどこに子要素をネストするか指定できます。例えば、以下の UXML テンプレートファイルが Assets/MyTemplate.uxml としてある場合:

<ui:UXML xmlns:ui="UnityEngine.UIElements" ...>
    <ui:Label text="Group Title" name="groupTitle" />
    <ui:VisualElement name="group-container" content-container="anyValue">
         <!--Add child elements here -->
    </ui:VisualElement>
    <ui:VisualElement />
</ui:UXML>

以下のように、子要素のネストされたテンプレートを適用できます。

<ui:UXML xmlns:ui="UnityEngine.UIElements" ...>
    <ui:Template path="Assets/MyTemplate.uxml" name="my-template"/>
    <ui:Instance template="my-template">
        <ui:Label text="Test"/> <!--This label element is instantiated inside the `group-container` element-->
    </ui:Instance>
</ui:UXML>

ノート: content-container 属性には任意の値を指定できます。

その他の参考資料

UXML にスタイルを加える
UXML から他のファイルを参照する