プレハブ とは、シーン内で複数回インスタンス化できる、あらかじめ作成されたゲームオブジェクトのことです。プレハブは、再利用可能なコンポーネントの作成に役立ちます。UI Toolkit のビジュアル要素はゲームオブジェクトではないので、プレハブには当てはまりません。ただし、要素の特定の階層をロジックでカプセル化する再利用可能な UI コンポーネントとして カスタムコントロールを作成 することが可能です。UI Toolkit では、UI をゲームやアプリケーションのコードから分離することが推奨されるため、UXML を使用して構造を定義し、USS を使用して見た目を定義し、C# を使用してカスタムコントロールのロジックを定義することができます。
再利用可能な UI コンポーネント - 例えば、以下のような、キャラクターの画像と体力と攻撃力を表示するカードの、CardElement
と呼ばれるカスタムコントロール - を作成するとします。
これは、以下のおおまかな手順で作成できます。
C# で、CardElement という カスタム要素タイプ を宣言します。
UXML で、カスタムコントロールの階層を定義します。2 つのアプローチが使用可能です。どちらのアプローチでも、C# と親 UXML で CardElement
をインスタンス化できます。
カスタムコントロールの子要素への参照を見つけます。
プロパティとメソッドを公開し、(C# のクラスの場合と同様に) カスタムコントロールのロジックをカプセル化します。
カスタムコントロールをゲームやアプリケーションのコードに接続します。イベントコールバックを登録してユーザーとのインタラクションを実装することもできます。
この方法では、カスタム要素 CardElement を階層 UXML ドキュメントに含め、その直下で子要素を宣言し、階層 UXML ドキュメントを テンプレート として使用します。この方法では、階層 UXML ドキュメント内の UI 構造が固定された、よりシンプルなソリューションが提供されます。
以下の C# と UXML の例は、UXML 優先のアプローチを使用して再利用可能な UI を作成する方法を示すものです。
CardElement カスタムコントロールを定義する C# スクリプトを作成します。カスタムコントロールクラスは CardElement に画像とバッジの値を割り当てます。
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
public class CardElement : VisualElement
{
// Expose the custom control to UXML and UI Builder.
public new class UxmlFactory : UxmlFactory<CardElement> {}
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Use the Init() approach instead of a constructor because
// we don't have children yet.
public void Init(Texture2D image, int health, int attack)
{
portraitImage.style.backgroundImage = image;
attackBadge.text = health;
healthBadge.text = attack;
}
// Custom controls need a default constructor.
public CardElement() {}
}
CardElement の階層構造を定義する UXML ドキュメント (CardElement.uxml
) を作成します。この例では、USS ファイルを使用して CardElement のスタイルを設定します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<CardElement>
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</CardElement>
</ui:UXML>
カスタムコントロールをゲームに接続するには、以下を行います。
CardElement.uxml
を親 UXML ドキュメント内でインスタンス化します。UI Builder では、階層 UXML とこの UXML ドキュメントを 行き来する ことができます。CardElement
を含む CardElement.uxml
をインスタンス化します。CardElement をシーンに追加する前に、UQuery を使って CardElement を見つける必要があります。カスタムコントロールをシーンに追加した後で Init()
を呼び出します。
また、要素とのインタラクションを行うためのクリックイベントなど、ゲームプレイに関連するアクションを追加することもできます。
親 UXML の内部でインスタンス化する
以下は、UXML でのインスタンス化の例です。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:Template name="CardElement" src="CardElement.uxml"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
</ui:UXML>
ゲームで UXML ドキュメントをレンダリングする方法については、ゲームビューでの UI のレンダリングに関するドキュメント 参照してください。
C# で直接インスタンス化する
ノート: このページ内のサンプルコードは学習目的のため、Resources フォルダー を使用する方法で UXML ファイルを読み込んでいます。ただし、この方法はあまり拡張性がありません。製品版プロジェクトでは 他の方法 で参照を読み込むことをお勧めします。
以下は、C# でのインスタンス化の例です。
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Load the UXML document that defines the hierarchy of CardElement.
// It assumes the UXML file is placed at the "Resources" folder.
VisualTreeAsset template = Resources.Load<VisualTreeAsset>("CardElement");
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
// Instantiate a template container.
var templateContainer = template.Instantiate();
// Find the custom element inside the template container.
var cardElement = templateContainer.Q<CardElement>();
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
// Initialize the card.
cardElement.Init(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
このアプローチでは、階層 UXML ドキュメントに子要素のみを含め、C# を使用して CardElement クラス定義に 階層 UXML ドキュメントをロード します。このアプローチでは、カスタムコントロールに柔軟な UI 構造が提供されます。例えば、特定の条件に応じて異なる階層 UXML ドキュメントをロードできます。
以下の C# と UXML の例は、要素優先のアプローチを使用して再利用可能な UI を作成する方法を示すものです。
CardElement カスタムコントロールを定義する C# スクリプトを作成します。CardElement に画像とバッジの値を割り当てるコンストラクターを定義 するのに加え、このカスタムコントロールは、クラス定義内に階層 UXML ドキュメントをロードします。
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
public class CardElement : VisualElement
{
// Expose the custom control to UXML and UI Builder.
public new class UxmlFactory : UxmlFactory<CardElementA> {}
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Custom controls need a default constructor. This default constructor
// calls the other constructor in this class.
public CardElement() {}
// Define a constructor that loads the UXML document that defines
// the hierarchy of CardElement and assigns an image and badge values.
public CardElement(Texture2D image, int health, int attack)
{
// It assumes the UXML file is called "CardElement.uxml" and
// is placed at the "Resources" folder.
var asset = Resources.Load<VisualTreeAsset>("CardElement");
asset.CloneTree(this);
portraitImage.style.backgroundImage = image;
attackBadge.text = health.ToString();
healthBadge.text = attack.ToString();
}
}
ノート: パフォーマンスに関して懸念がある場合は、遅延初期化を使用して、フィールドで参照をキャッシュし、クエリの再評価を頻繁に行いすぎないようにします。
CardElement の子要素の階層を定義する UXML 文書 (CardElement.uxml
) を作成します。この例では、USS ファイルで CardElement のスタイルを設定しています。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</ui:UXML>
以下を行うことで、カスタムコントロールをゲームに接続できます。
CardElement.uxml
をインスタンス化します。UI Builder では、子要素が C# からロードされるため、階層 UXML とこの UXML ドキュメントを行き来することはできません。CardElement
を格納する CardElement.uxml
をインスタンス化します。カスタムコントロールをシーンに追加する前にコンストラクターを呼び出します。
また、要素とのインタラクションを行うためのクリックイベントなど、ゲームプレイに関連するアクションを追加することもできます。
親 UXML の内部でインスタンス化する
以下は、UXML でのインスタンス化の例です。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<CardElement />
<CardElement />
<CardElement />
</ui:UXML>
ゲームで UXML ドキュメントをレンダリングする方法については、ゲームビューでの UI のレンダリングに関するドキュメント 参照してください。
C# で直接インスタンス化する
以下は、C# でのインスタンス化の例です。
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
var cardElement = new CardElement(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
プロジェクトの UI が複雑になる場合は、ロジックをより高いレベルで分離することが推奨されます。そうすることで、ゲームやアプリケーションの他の部分の UI 構成が行いやすくなります。
このページで紹介されている概念を応用すれば、小さな汎用的なコンポーネントから、徐々に、より特化したコンポーネントを作成できます。例えば、メインのタイトル画面を作成し、そこからユーザーがオプションメニューと About セクションにアクセスできるようにするには、3 つの異なる子 UXML ドキュメントを持つ TitleScreenManager 要素を作成します。それぞれの子が独自の要素 (Title、Options、About) を定義するようにします。
詳細は こちら の YouTube 動画を参照してください。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.