Unity 拡張マークアップ言語 (UXML, Unity eXtensible Markup Language) ファイルは、ユーザーインターフェースの構造を定義するテキストファイルです。UXML 形式は、HTML、XAML、XML にヒントを得ています。これらの形式を使ったことがある人は、UXML と似ていることに気づくでしょう。しかし、UXML 形式には、Unity との作業を効率的に行うための相違点があります。
このセクションでは、Unity がサポートする UXML 形式について説明し、UXML テンプレートの記述、読み込み、定義の詳細について説明します。また、新しい要素の定義や UQuery の使い方に関する情報も提供します。
UXML を使用することで、技術的に精通していないユーザーが Unity 内でユーザーインターフェースを作成しやすくなります。UXML では以下のことが可能です。
これにより、開発者はアセットのインポート、ロジックの定義、データの処理などの技術的な作業を行うことができます。
UI Toolkit を使うと、独自のユーザーインターフェースコンポーネントと要素を定義することができます。
UXML ファイルを使用して新しい要素を定義する前に、VisualElement
かそのサブクラスの 1 つから新しいクラスを派生させ、次にこの新しいクラス内で適切な機能を実装する必要があります。新しいクラスにはデフォルトコンストラクターを実装する必要があります。
例えば、以下のコードは新しい StatusBar
クラスを派生させ、デフォルトのコンストラクターを実装します。
class StatusBar : VisualElement
{
public StatusBar()
{
m_Status = String.Empty;
}
string m_Status;
public string status { get; set; }
}
UXML ファイルを読み込むときに UI Toolkit が新しいクラスをインスタンス化できるようにするには、クラスの Factory を定義する必要があります。Factory が特別なことを行う必要がない限り、UxmlFactoy <T>
から Factory を派生させることができます。Factory クラスをコンポーネントクラス内に配置することが推奨されます。
例えば、以下のコードは StatusBar
クラスの Factory を UxmlFactory <T>
から派生させてファクトリを定義する方法を示しています。 Factory は UxmlFactory
という名前です。
class StatusBar : VisualElement
{
public new class UxmlFactory : UxmlFactory<StatusBar> {}
// ...
}
この Factory を定義すると、UXML ファイルの <StatusBar>
要素を使用することができます。
新しいクラスに UXML の特性 (traits) を定義し、その特性を使用するように Factory を設定することができます。
例えば、下のコードは UXML の Traits クラスを定義して status
プロパティーを StatusBar
クラスのプロパティーとして初期化する方法を示しています。status プロパティーは XML データから初期化されます。
class StatusBar : VisualElement
{
public new class UxmlFactory : UxmlFactory<StatusBar, UxmlTraits> {}
public new class UxmlTraits : VisualElement.UxmlTraits
{
UxmlStringAttributeDescription m_Status = new UxmlStringAttributeDescription { name = "status" };
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get { yield break; }
}
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
((StatusBar)ve).status = m_Status.GetValueFromBag(bag, cc);
}
}
// ...
}
UxmlTraits
には 2 つの目的があります。
UxmlTraits
を使って、新しく作られたオブジェクトを初期化します。UxmlTraits
は分析され、要素に関する情報が取得されます。この情報は XML スキーマディレクティブに変換されます。上のサンプルコードは以下の処理を行います。
m_Status
の宣言は XML 属性 status
を定義します。uxmlChildElementsDescription
は StatusBar
要素に子がないことを示す空の IEnumerable
を返します。Init()
メンバーは、XML パーサーからプロパティバッグの status
属性の値を読み込み、StatusBar.status
プロパティにこの値に設定します。StatusBar
クラスの中に UxmlTraits
クラスを置くことによって Init()
メソッドが StatusBar
のプライベートメンバーにアクセスできるようにします。UxmlTraits
クラスは基本クラス UxmlTraits
を継承しているので、基本クラスの属性を共有します。Init()
は base.Init()
を呼び出して基本クラスのプロパティを初期化します。前述のコード例は UxmlStringAttributeDescription
クラスで文字列属性を宣言しています。UI Toolkit は以下のタイプの属性をサポートし、それぞれが C# 型を XML 型にリンクします。
属性 | 属性値 |
---|---|
UxmlStringAttributeDescription |
文字列 |
UxmlFloatAttributeDescription |
C# float 型の範囲の単精度浮動小数点値 |
UxmlDoubleAttributeDescription |
C# double 型の範囲の倍精度浮動小数点値 |
UxmlIntAttributeDescription |
C# int 型の範囲の整数値 |
UxmlLongAttributeDescription |
C# long 型の範囲の整数値 |
UxmlBoolAttributeDescription |
true または false
|
UxmlColorAttributeDescription |
色を表す文字列 (#FFFFFF ) |
UxmlEnumAttributeDescription<T> |
Enum 型 T 値の 1 つを表す文字列 |
上記のコード例では、uxmlChildElementsDescription
は StatusBar
要素が子を受け付けないことを示す空の IEnumerable
を返します。
要素が任意の型の子を受け入れるには、uxmlChildElementsDescription
プロパティーをオーバーライドする必要があります。例えば、StatusBar
要素が任意の型の子を受け入れるためには、uxmlChildElementsDescription
プロパティーを以下のように指定する必要があります。
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get
{
yield return new UxmlChildElementDescription(typeof(VisualElement));
}
}
C# で新しい要素を定義したら、要素を UXML ファイルで使用することができます。新しい要素が新しい名前空間で定義されている場合は、名前空間のプレフィックスを定義する必要があります。名前空間のプレフィックスはルートの <UXML>
要素への属性として宣言され、要素をスコープするときに完全な名前空間名を置き換えます。
名前空間プレフィックスを定義するには、定義したいそれぞれの名前空間プレフィックスのアセンブリに UxmlNamespacePrefix
属性を加えます。
[assembly:UxmlNamespacePrefix( "My.First.Namespace"、 "first")]
[assembly:UxmlNamespacePrefix( "My.Second.Namespace"、 "second")]
これは、アセンブリの C# ファイルのルートレベル (任意の名前空間の外側) で行います。
スキーマ生成システムは以下を行います。
<UXML>
要素の属性として名前空間プレフィックスの定義を加えます。xsi:schemaLocation
属性に名前空間のスキーマファイルの場所を含めます。プロジェクトの UXML スキーマを更新する必要があります。Assets > Update UXML Schema を選択して、テキストエディターが新しい要素を認識できるようにします。
定義したプレフィックスは、Project/Assets/Editor
フォルダーの Create > UI Toolkit > Editor Window を選択すると、新しく作成された UXML で利用可能です。
IUxmlFactory.uxmlName
と IUXmlFactory.uxmlQualifiedName
プロパティをオーバーライドすることによって、UXML 名をカスタマイズできます。uxmlName
が名前空間内で一意であり、uxmlQualifiedName
がプロジェクト内で一意であることを確認してください。
両方の名前が一意でない場合は、アセンブリをロードしようとすると例外がスローされます。
次のサンプルコードは、UXML 名をオーバーライドしてカスタム化する方法を示しています。
public class FactoryWithCustomName : UxmlFactory<..., ...>
{
public override string uxmlName
{
get { return "UniqueName"; }
}
public override string uxmlQualifiedName
{
get { return uxmlNamespace + "." + uxmlName; }
}
}
デフォルトでは、IUxmlFactory
は要素をインスタンス化し、要素の名前を使用して要素を選択します。
IUXmlFactory.AcceptsAttributeBag
をオーバーライドすることで、選択プロセスで要素の属性値を考慮させることができます。次に、要素の属性を調べて、UXML 要素のオブジェクトをインスタンス化できるかどうかを決定します。
これは、VisualElement
クラスがジェネリックである場合に便利です。この場合、クラスの特殊化のためのクラス Factory で XML の type
属性の値を調べることができます。値に応じて、インスタンス化が行われる、または拒否されます。例は、PropertyControl <T>
の実装を参照してください。
複数の Factory が要素をインスタンス化できる場合は、最初に登録された Factory が選択されます。
基本クラスで宣言された属性のデフォルト値は UxmlTraits
クラスの defaultValue
を設定することで変更できます。
例えば、以下のコードは m_TabIndex
のデフォルト値を変更する方法を示しています。
class MyElementTraits : VisualElement.UxmlTraits
{
public MyElementTraits()
{
m_TabIndex.defaultValue = 0;
}
}
デフォルトで、XML スキーマが生成されると、要素は任意の属性を持つことができます。
UxmlTraits
クラスで宣言されたもの以外の属性の値は制限されません。これは、宣言された属性の値が宣言に一致するかどうかをチェックする XML バリデーターとは対照的です。
追加の属性は IUxmlAttributes
バッグに含まれ、IUxmlFactory.AcceptsAttributBag()
と IUxmlFactory.Init()
関数に渡されます。これらの追加属性を使用するかどうかは、 Factory の実装によって異なります。デフォルトの動作では、追加属性を破棄します。
つまり、これらの追加の属性はインスタンス化された VisualElement
にアタッチされず、これらの属性は UQuery
でクエリできません。
新しい要素を定義するとき、 UxmlTraits
コンストラクターで UxmlTraits.canHaveAnyAttribute
プロパティを false
に設定することによって、受け入れられた属性を明示的に宣言された属性に限定することができます。
スキーマ定義ファイルは、属性と、各 UXML 要素が含むことのできる属性の子要素を指定します。正しいドキュメントを作成して、ドキュメントを検証するためのガイドとして、スキーマ定義ファイルを使用します。
UXML テンプレートファイルでは、<UXML>
ルート要素の xsi:noNamespaceSchemaLocation
属性と xsi:schemaLocation
属性は、スキーマ定義ファイルの場所を指定します。
Assets > Create > UI Toolkit > Editor Window の順に選択すると、プロジェクトで使用する VisualElement
サブクラスから収集された最新の情報で自動的にスキーマ定義を更新できます。UXML スキーマファイルを強制的に更新するには、 Assets > Update UXML Schema を選択します。
ノート: テキストエディターの中には xsi:noNamespaceSchemaLocation
属性を認識できないものがあります。テキストエディターがスキーマ定義ファイルを見つけることができない場合は、xsi:schemaLocation
属性も指定する必要があります。