UnityのUI ToolkitでTreeViewを使ってシングルカラムのツリービューを実装する方法についてまとめました。
Unity 2022.2.17
はじめに
UI ToolkitのTreeView
を使うと、下図のようなツリー状の見た目を作れます。
本記事ではこのようなTreeViewを持ったEditorWindowの作り方についてまとめます。
なおマルチカラムのツリービューに関しては以下の記事で説明しています。
UXMLファイルを作成する
まずUXMLファイルでレイアウトを作成します。
以下のようにTreeView
を設定します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False"> <ui:TreeView view-data-key="unity-tree-view" focusable="true" /> </ui:UXML>
これをeditor_layout.uxml
として保存しておきます。
次にリストに表示する各項目のレイアウトを作成します。
といっても単純にラベルを表示しているだけです。
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False"> <ui:Label text="Label" /> </ui:UXML>
これをitem_layout.uxml
として保存しておきます。
EditorWindowを作成する
次に以下の通りEditorWindow
のスクリプトを作成します。
using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; public sealed class Example : EditorWindow { [SerializeField] private VisualTreeAsset editorLayout; [SerializeField] private VisualTreeAsset labelItemLayout; private readonly List<TreeViewItemData<Item>> _rootItems = new(); private void Reset() { var id = 0; for (var i = 0; i < 10; i++) { // 子アイテムのリストを作成 var items = new List<TreeViewItemData<Item>>(10); for (var j = 0; j < 10; j++) { var item = new TreeViewItemData<Item>(id++, new Item { name = $"Item {j}" }); items.Add(item); } // ルートアイテムを作成し、子アイテムを追加 var rootItem = new TreeViewItemData<Item>(id++, new Item { name = $"Group {i}" }, items); // ルートアイテムのみをデータソースに追加 _rootItems.Add(rootItem); } } private void CreateGUI() { editorLayout.CloneTree(rootVisualElement); var treeView = rootVisualElement.Q<TreeView>(); // データソースを設定 treeView.SetRootItems(_rootItems); // アイテムのレイアウトを作成する処理 treeView.makeItem = labelItemLayout.CloneTree; // アイテムの内容を設定する処理 treeView.bindItem = (e, i) => e.Q<Label>().text = treeView.GetItemDataForIndex<Item>(i).name; } [MenuItem("Window/Example")] public static void ShowWindow() { GetWindow<Example>(); } [Serializable] public struct Item { public string name; } }
説明はコメントに書いた通りです。
各アイテムに対してレイアウトを生成し、アイテムの内容をバインドできます。
実行結果
Window > Exampleからウィンドウを開くと以下の結果が得られます。
正常に実装できていることを確認できました。