バージョン: 2022.3+
この例では、リストビューのランタイム UI を作成する方法を示します。この例では、UXML ファイルと USS ファイルを直接使用して、UI の構造体とスタイルを作成します。UI Toolkit を初めて使用する場合に、UI Builder を使用して UI を作成するには、UI Builder を使用した UI の例の作成を参照してください。
この例では、簡単なキャラクター選択画面を作成します。左側のリストからキャラクターの名前をクリックすると、右側にキャラクターの詳細が表示されます。
この例で作成する完成したファイルは、こちらの GitHub リポジトリにあります。
このガイドは、Unity エディター、UI Toolkit、および C# スクリプトに精通している開発者を対象としています。始める前に、以下の点を理解しておいてください。
メインビューの UI Document と USS ファイルを作成し、ビジュアル要素のスタイルを設定します。UI Document に 2 つのビジュアル要素をコンテナとして追加します。1 つはキャラクター名のリストが含まれる要素、もう 1 つは選択したキャラクターの詳細情報が含まれる要素です。
Unity で任意のテンプレートを使用してプロジェクトを作成します。
Project ウィンドウに UI という名前のフォルダーを作成し、すべての UI Document ファイルとスタイルシートファイルを保存します。
UI フォルダーに、以下の内容で、MainView.uxml という名前の UI Document を作成します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="MainView.uss" />
<ui:VisualElement name="background">
<ui:VisualElement name="main-container">
<ui:ListView focusable="true" name="character-list" />
<ui:VisualElement name="right-container">
<ui:VisualElement name="details-container">
<ui:VisualElement name="details">
<ui:VisualElement name="character-portrait" />
</ui:VisualElement>
<ui:Label text="Label" name="character-name" />
<ui:Label text="Label" display-tooltip-when-elided="true" name="character-class" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
UI フォルダーに、以下の内容で MainView.uss という名前の USS スタイルシートを作成します。
#background {
flex-grow: 1;
align-items: center;
justify-content: center;
background-color: rgb(115, 37, 38);
}
#main-container {
flex-direction: row;
height: 350px;
}
#character-list {
width: 230px;
border-color: rgb(49, 26, 17);
border-width: 4px;
background-color: rgb(110, 57, 37);
border-radius: 15px;
margin-right: 6px;
}
#character-name {
-unity-font-style: bold;
font-size: 18px;
}
#character-class {
margin-top: 2px;
margin-bottom: 8px;
padding-top: 0;
padding-bottom: 0;
}
#right-container {
justify-content: space-between;
align-items: flex-end;
}
#details-container {
align-items: center;
background-color: rgb(170, 89, 57);
border-width: 4px;
border-color: rgb(49, 26, 17);
border-radius: 15px;
width: 252px;
justify-content: center;
padding: 8px;
height: 163px;
}
#details {
border-color: rgb(49, 26, 17);
border-width: 2px;
height: 120px;
width: 120px;
border-radius: 13px;
padding: 4px;
background-color: rgb(255, 133, 84);
}
#character-portrait {
flex-grow: 1;
-unity-background-scale-mode: scale-to-fit;
}
.unity-collection-view__item {
justify-content: center;
}
リスト内の個々のエントリーの UI Document とスタイルシートを作成します。キャラクターリストのエントリーは、色のついた背景フレームとキャラクター名で構成されています。
UI フォルダーに、以下の内容で、ListEntry.uxml という名前の UI Document を作成します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="ListEntry.uss" />
<ui:VisualElement name="list-entry">
<ui:Label text="Label" display-tooltip-when-elided="true" name="character-name" />
</ui:VisualElement>
</ui:UXML>
UI フォルダーに、以下の内容で ListEntry.uss という名前のスタイルシートファイルを作成します。
#list-entry {
height: 41px;
align-items: flex-start;
justify-content: center;
padding-left: 10px;
background-color: rgb(170, 89, 57);
border-color: rgb(49, 26, 17);
border-width: 2px;
border-radius: 15px;
}
#character-name {
-unity-font-style: bold;
font-size: 18px;
color: rgb(49, 26, 17);
}
UI のキャラクターリストを埋めるサンプルデータを作成します。キャラクターリストに、キャラクター名、クラス、ポートレート画像を保持するクラスを作成します。
Asset フォルダーに、C# スクリプトを格納する Scripts という名前のフォルダーを作成します。
Scripts フォルダーに、以下の内容の C# スクリプトを作成し CharacterData.cs と命名します。
using UnityEngine;
public enum ECharacterClass
{
Knight, Ranger, Wizard
}
[CreateAssetMenu]
public class CharacterData : ScriptableObject
{
public string CharacterName;
public ECharacterClass Class;
public Sprite PortraitImage;
}
Assets フォルダーに、Resources という名前のフォルダーを作成します。
Resources フォルダーに、すべてのサンプルキャラクターデータを格納する Characters という名前のフォルダーを作成します。
Characters フォルダー内で右クリックし、Create > Character Data を選択して ScriptableObject のインスタンスを作成します。
CharacterData インスタンスを追加作成し、プレースホルダーデータを入力します。
サンプルシーン内に UIDocument ゲームオブジェクトを作成し、UI Document をソースアセットとして加えます。
以下のクラスで 2 つの C# スクリプトを作成します。
CharacterListEntryController クラス。キャラクター名のラベルにアクセスし、指定したキャラクターインスタンスの名前を表示するように設定する必要があります。CharacterListController クラスと、それをインスタンス化してビジュアルツリーに割り当てる MonoBehaviour スクリプト。
ノート: CharacterListEntryController クラスは MonoBehaviour ではありません。UI Toolkit のビジュアル要素はゲームオブジェクトではないため、コンポーネントをアタッチすることはできません。代わりに、クラスを CharacterListController クラスの userData プロパティにアタッチします。
Scripts フォルダーに、以下の内容の C# スクリプトを作成し CharacterListEntryController.cs と命名します。
using UnityEngine.UIElements;
public class CharacterListEntryController
{
Label m_NameLabel;
// This function retrieves a reference to the
// character name label inside the UI element.
public void SetVisualElement(VisualElement visualElement)
{
m_NameLabel = visualElement.Q<Label>("character-name");
}
// This function receives the character whose name this list
// element is supposed to display. Since the elements list
// in a `ListView` are pooled and reused, it's necessary to
// have a `Set` function to change which character's data to display.
public void SetCharacterData(CharacterData characterData)
{
m_NameLabel.text = characterData.CharacterName;
}
}
Scripts フォルダーに、以下の内容の C# スクリプトを作成し CharacterListController.cs と命名します。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class CharacterListController
{
// UXML template for list entries
VisualTreeAsset m_ListEntryTemplate;
// UI element references
ListView m_CharacterList;
Label m_CharClassLabel;
Label m_CharNameLabel;
VisualElement m_CharPortrait;
List<CharacterData> m_AllCharacters;
public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{
EnumerateAllCharacters();
// Store a reference to the template for the list entries
m_ListEntryTemplate = listElementTemplate;
// Store a reference to the character list element
m_CharacterList = root.Q<ListView>("character-list");
// Store references to the selected character info elements
m_CharClassLabel = root.Q<Label>("character-class");
m_CharNameLabel = root.Q<Label>("character-name");
m_CharPortrait = root.Q<VisualElement>("character-portrait");
FillCharacterList();
// Register to get a callback when an item is selected
m_CharacterList.selectionChanged += OnCharacterSelected;
}
void EnumerateAllCharacters()
{
m_AllCharacters = new List<CharacterData>();
m_AllCharacters.AddRange(Resources.LoadAll<CharacterData>("Characters"));
}
void FillCharacterList()
{
// Set up a make item function for a list entry
m_CharacterList.makeItem = () =>
{
// Instantiate the UXML template for the entry
var newListEntry = m_ListEntryTemplate.Instantiate();
// Instantiate a controller for the data
var newListEntryLogic = new CharacterListEntryController();
// Assign the controller script to the visual element
newListEntry.userData = newListEntryLogic;
// Initialize the controller script
newListEntryLogic.SetVisualElement(newListEntry);
// Return the root of the instantiated visual tree
return newListEntry;
};
// Set up bind function for a specific list entry
m_CharacterList.bindItem = (item, index) =>
{
(item.userData as CharacterListEntryController)?.SetCharacterData(m_AllCharacters[index]);
};
// Set a fixed item height matching the height of the item provided in makeItem.
// For dynamic height, see the virtualizationMethod property.
m_CharacterList.fixedItemHeight = 45;
// Set the actual item's source list/array
m_CharacterList.itemsSource = m_AllCharacters;
}
void OnCharacterSelected(IEnumerable<object> selectedItems)
{
// Get the currently selected item directly from the ListView
var selectedCharacter = m_CharacterList.selectedItem as CharacterData;
// Handle none-selection (Escape to deselect everything)
if (selectedCharacter == null)
{
// Clear
m_CharClassLabel.text = "";
m_CharNameLabel.text = "";
m_CharPortrait.style.backgroundImage = null;
return;
}
// Fill in character details
m_CharClassLabel.text = selectedCharacter.Class.ToString();
m_CharNameLabel.text = selectedCharacter.CharacterName;
m_CharPortrait.style.backgroundImage = new StyleBackground(selectedCharacter.PortraitImage);
}
}
CharacterListController は MonoBehaviour ではないため、ゲームオブジェクトに直接アタッチすることはできません。これを解決するには、MonoBehaviour スクリプトを作成し、UIDocument と同じゲームオブジェクトにアタッチします。このスクリプトでは、MainView.uxml はすでに UIDocument コンポーネントによってインスタンス化されているため、インスタンス化する必要はありません。代わりに UIDocument コンポーネントにアクセスし、すでにインスタンス化されているビジュアルツリーのリファレンスを取得します。次に、CharacterListController のインスタンスを作成し、ビジュアルツリーのルート要素と、個々のリスト要素に使用される UXML テンプレートを渡します。
ノート: UI がリロードされると、UIDocument コンポーネントを含む同じゲームオブジェクト上の関連する MonoBehaviour コンポーネントはすべてリロード前に無効になり、リロード後に再び有効になります。したがって、UI 関連のコードは、この MonoBehaviour の OnEnable メソッドと OnDisable メソッド内に配置する必要があります。詳細については、ゲームビューでの UI のレンダリングを参照してください。
Scripts フォルダーに、以下の内容の C# スクリプトを作成し MainView.cs と命名します。
using UnityEngine;
using UnityEngine.UIElements;
public class MainView : MonoBehaviour
{
[SerializeField]
VisualTreeAsset m_ListEntryTemplate;
void OnEnable()
{
// The UXML is already instantiated by the UIDocument component
var uiDocument = GetComponent<UIDocument>();
// Initialize the character list controller
var characterListController = new CharacterListController();
characterListController.InitializeCharacterList(uiDocument.rootVisualElement, m_ListEntryTemplate);
}
}
SampleScene で、UIDocument を選択します。
Inspector ウィンドウで MainView.cs を Add Component にドラッグします。
ListEntry.uxml を ListEntry Template フィールドにドラッグします。
再生モードに切り替えると、ゲームビューに UI が表示されます。