Unity 6.3
0 онлайн 101 гостей 3 в системе
Вход
UI системы Шаг 113 из 317

Создание представлений списка и дерева

Список и дерево представления являются общими особенностями в UI дизайн. Вы можете использовать UI Toolkit для создания списков и деревьев внутри пользовательского окна Редактора или времени выполнения. В этом примере показано, как создать списки и деревья внутри пользовательского окна Редактора. Вы настраиваете структуру списков и деревьев с помощью UXML и затем динамически заполнить их в вашем C# скрипта.

Примерный обзор

В этом примере создаются четыре окна Редактора, в которых отображаются следующие элементы:

  • Список планет с одной колонкой
  • Список планет с двумя колонками
  • Деревянный вид планет
  • Деревянный вид планет с двумя колонками

Вы можете найти завершенные файлы, созданные этим примером, в хранилище GitHub.

Предварительные условия

Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:

Создать данные в C#

Создайте данные в скрипте C#, который состоит из двух групп планет и корневых узлов для дерева представления.

  1. Создайте проект в Unity с любым шаблоном.

  2. В окне Project создайте папку Editor.

  3. В папке Editor создайте скрипт C# с именем PlanetsWindow.cs.

  4. Заменить содержимое PlanetsWindow.cs следующим текстом:

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    using UnityEngine.UIElements;
    
    // Base class for all windows that display planet information.
    public class PlanetsWindow : EditorWindow
    {
        [SerializeField]
        protected VisualTreeAsset uxmlAsset;
    
        // Nested interface that can be either a single planet or a group of planets.
        protected interface IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get;
            }
        }
    
        // Nested class that represents a planet.
        protected class Planet : IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get;
            }
    
            public Planet(string name, bool populated = false)
            {
                this.name = name;
                this.populated = populated;
            }
        }
    
        // Nested class that represents a group of planets.
        protected class PlanetGroup : IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get
                {
                    var anyPlanetPopulated = false;
                    foreach (Planet planet in planets)
                    {
                        anyPlanetPopulated = anyPlanetPopulated || planet.populated;
                    }
                    return anyPlanetPopulated;
                }
            }
    
            public readonly IReadOnlyList<Planet> planets;
    
            public PlanetGroup(string name, IReadOnlyList<Planet> planets)
            {
                this.name = name;
                this.planets = planets;
            }
        }
    
        // Data about planets in our solar system.
        protected static readonly List<PlanetGroup> planetGroups = new List<PlanetGroup>
        {
            new PlanetGroup("Inner Planets", new List<Planet>
            {
                new Planet("Mercury"),
                new Planet("Venus"),
                new Planet("Earth", true),
                new Planet("Mars")
            }),
            new PlanetGroup("Outer Planets", new List<Planet>
            {
                new Planet("Jupiter"),
                new Planet("Saturn"),
                new Planet("Uranus"),
                new Planet("Neptune")
            })
        };
    
        // Expresses planet data as a list of the planets themselves. Needed for ListView and MultiColumnListView.
        protected static List<Planet> planets
        {
            get
            {
                var retVal = new List<Planet>(8);
                foreach (var group in planetGroups)
                {
                    retVal.AddRange(group.planets);
                }
                return retVal;
            }
        }
    
        // Expresses planet data as a list of TreeViewItemData objects. Needed for TreeView and MultiColumnTreeView.
        protected static IList<TreeViewItemData<IPlanetOrGroup>> treeRoots
        {
            get
            {
                int id = 0;
                var roots = new List<TreeViewItemData<IPlanetOrGroup>>(planetGroups.Count);
                foreach (var group in planetGroups)
                {
                    var planetsInGroup = new List<TreeViewItemData<IPlanetOrGroup>>(group.planets.Count);
                    foreach (var planet in group.planets)
                    {
                        planetsInGroup.Add(new TreeViewItemData<IPlanetOrGroup>(id++, planet));
                    }
    
                    roots.Add(new TreeViewItemData<IPlanetOrGroup>(id++, group, planetsInGroup));
                }
                return roots;
            }
        }
    }
    

Создание представления списка

Чтобы создать представление списка, сначала используйте конструктор UI для создания элемента управления ListView UI. Затем создайте окно редактора с помощью ListView и определите, где получить данные для списка в скрипте C#. Наконец, сделайте ссылку на файл UXML в скрипте C#.

  1. Щелкните правой кнопкой мыши папку Editor.

  2. Выберите Создать > UI Toolkit > Окно редактора.

  3. В поле C# введите PlanetsListView и снимите флажок USS. Это создаст два файла: PlanetsListView.uxml и PlanetsListView.cs.

  4. Дважды щелкните PlanetsListView.uxml, чтобы открыть его в UI Builder.

  5. В окне Hierarchy удалите контроль Label и добавьте контроль ListView.

  6. Выберите ListView в окне Hierarchy.

  7. В окне Inspector установите Fixed Item Height на 20.

  8. Сохраните изменения. Ваш PlanetsListView.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:ListView fixed-item-height="20" />
    </ui:UXML>
    
  9. Заменить содержимое PlanetsListView.cs следующим текстом:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsListView : PlanetsWindow
    {
        [MenuItem("Planets/Standard List")]
        static void Summon()
        {
            GetWindow<PlanetsListView>("Standard Planet List");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var listView = rootVisualElement.Q<ListView>();
    
            // Set ListView.itemsSource to populate the data in the list.
            listView.itemsSource = planets;
    
            // Set ListView.makeItem to initialize each entry in the list.
            listView.makeItem = () => new Label();
    
            // Set ListView.bindItem to bind an initialized entry to a data item.
            listView.bindItem = (VisualElement element, int index) =>
                (element as Label).text = planets[index].name;
        }
    }
    
  10. В Unity выберите PlanetsListView.cs в окне Project, а затем перетащите PlanetsListView.uxml в поле Uxml в Inspector.

  11. Из меню выберите Планеты > Стандартный список, чтобы увидеть список планет.

Список планет в окне Unity Editor.
Список планет в окне Unity Editor.

Создание представления списка с несколькими столбцами

Чтобы создать представление списка с несколькими столбцами, сначала создайте MultiColumnListView UI контроллер, и определите количество столбцов и названия столбцов в файле UXML. Затем создайте пользовательское окно Редактора с MultiColumnListView и определите, где получить данные для списка в каждом столбце в скрипте C#. Наконец, укажите ссылку на файл UXML в скрипте C#.

  1. Щелкните правой кнопкой мыши папку Editor.

  2. Выберите Создать > UI Toolkit > UI Документ, чтобы создать файл UXML и назвать его PlanetsMultiColumnListView.uxml.

  3. Откройте PlanetsMultiColumnListView.uxml в текстовом редакторе.

  4. Заменить содержимое PlanetsMultiColumnListView.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:MultiColumnListView fixed-item-height="20">
            <!-- Columns and Column aren't Visual Elements or controls. They are considered attributes of MultiColumnListView. -->
            <ui:Columns>
                <ui:Column name="name" title="Name" width="80" />
                <ui:Column name="populated" title="Populated?" width="80" />
            </ui:Columns>
        </ui:MultiColumnListView>
    </ui:UXML>
    
  5. В папке Editor создайте файл C# с именем PlanetsMultiColumnListView.cs.

  6. Заменить содержимое PlanetsMultiColumnListView.cs следующим текстом:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsMultiColumnListView : PlanetsWindow
    {
        [MenuItem("Planets/Multicolumn List")]
        static void Summon()
        {
            GetWindow<PlanetsMultiColumnListView>("Multicolumn Planet List");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var listView = rootVisualElement.Q<MultiColumnListView>();
    
            // Set MultiColumnListView.itemsSource to populate the data in the list.
            listView.itemsSource = planets;
    
            // For each column, set Column.makeCell to initialize each cell in the column.
            // You can index the columns array with names or numerical indices.
            listView.columns["name"].makeCell = () => new Label();
            listView.columns["populated"].makeCell = () => new Toggle();
    
            // For each column, set Column.bindCell to bind an initialized cell to a data item.
            listView.columns["name"].bindCell = (VisualElement element, int index) =>
                (element as Label).text = planets[index].name;
            listView.columns["populated"].bindCell = (VisualElement element, int index) =>
                (element as Toggle).value = planets[index].populated;
        }
    }
    
  7. В Unity выберите PlanetsMultiColumnListView.cs в окне Project.

  8. Перетащите PlanetsMultiColumnListView.uxml в поле Uxml в Inspector.

  9. Из меню выберите Планеты > Многосторонний Список, чтобы увидеть список из двух столбцов. Один столбец содержит список планет. Второй столбец имеет переключатели, которые указывают, населена ли планета.

Список в окне Unity Editor с двумя столбцами, одним для планет и одним с флагом, указывающим, населена ли планета.
Список в окне Unity Editor с двумя столбцами, одним для планет и одним с флагом, указывающим, населена ли планета.

Создание дерева представления

Чтобы создать дерево представления в пользовательском Редакторе, сначала создайте TreeView UI контроллер в файле UXML. Затем создайте пользовательское окно Редактора с TreeView и определите, где получить данные для узлов дерева скриптом C#. Наконец, сделайте ссылку на файл UXML в скрипте C#.

  1. В папке Editor создайте файл UXML с именем PlanetsTreeView.uxml.

  2. Заменить содержимое PlanetsTreeView.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:TreeView fixed-item-height="20" />
    </ui:UXML>
    
  3. В папке Editor создайте файл C# с именем PlanetsTreeView.cs.

  4. Заменить содержимое PlanetsTreeView.cs следующим текстом:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsTreeView : PlanetsWindow
    {
        [MenuItem("Planets/Standard Tree")]
        static void Summon()
        {
            GetWindow<PlanetsTreeView>("Standard Planet Tree");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var treeView = rootVisualElement.Q<TreeView>();
    
            // Call TreeView.SetRootItems() to populate the data in the tree.
            treeView.SetRootItems(treeRoots);
    
            // Set TreeView.makeItem to initialize each node in the tree.
            treeView.makeItem = () => new Label();
    
            // Set TreeView.bindItem to bind an initialized node to a data item.
            treeView.bindItem = (VisualElement element, int index) =>
                (element as Label).text = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).name;
        }
    }
    
  5. В Unity выберите PlanetsTreeView.cs в окне Project.

  6. Перетащите PlanetsTreeView.uxml в поле Uxml в Inspector.

  7. Из меню выберите Планеты > Стандартное Дерево, чтобы увидеть два списка планет, сгруппированных по узлам. Рядом с каждым узлом находится стрелка. Если вы выберете стрелку, окно покажет планеты в группе.

Список в окне Unity Editor, организованном в два раздела: Внутренние планеты и Внешние планеты.
Список в окне Unity Editor, организованном в два раздела: Внутренние планеты и Внешние планеты.

Создание дерева с несколькими столбцами

Чтобы создать деревообразное представление с несколькими столбцами в пользовательском Редакторе, сначала создайте MultiColumnTreeView UI контроллер и определите столбцы в файле UXML. Затем создайте пользовательское окно Редактора с MultiColumnTreeView и определите, где получить данные для каждого столбца в скрипте C#. Наконец, укажите ссылку на файл UXML в скрипте C#.

  1. В папке Editor создайте файл UXML с именем PlanetsMultiColumnTreeView.uxml.

  2. Заменить содержимое PlanetsMultiColumnTreeView.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:MultiColumnTreeView fixed-item-height="20">
            <!-- Columns and Column aren't Visual Elements or controls; they are considered attributes of MultiColumnListView. -->
            <ui:Columns>
                <ui:Column name="name" title="Name" width="120" />
                <ui:Column name="populated" title="Populated?" width="80" />
            </ui:Columns>
        </ui:MultiColumnTreeView>
    </ui:UXML>
    
  3. В папке Editor создайте файл C# с именем PlanetsMultiColumnTreeView.cs.

  4. Заменить содержимое PlanetsMultiColumnTreeView.cs следующим текстом:

    using UnityEditor;
    using UnityEngine.UIElements;
        
    public class PlanetsMultiColumnTreeView : PlanetsWindow
    {
        [MenuItem("Planets/Multicolumn Tree")]
        static void Summon()
        {
            GetWindow<PlanetsMultiColumnTreeView>("Multicolumn Planet Tree");
        }
        
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var treeView = rootVisualElement.Q<MultiColumnTreeView>();
        
            // Call MultiColumnTreeView.SetRootItems() to populate the data in the tree.
            treeView.SetRootItems(treeRoots);
        
            // For each column, set Column.makeCell to initialize each node in the tree.
            // You can index the columns array with names or numerical indices.
            treeView.columns["name"].makeCell = () => new Label();
            treeView.columns["populated"].makeCell = () => new Toggle();
        
            // For each column, set Column.bindCell to bind an initialized node to a data item.
            treeView.columns["name"].bindCell = (VisualElement element, int index) =>
                (element as Label).text = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).name;
            treeView.columns["populated"].bindCell = (VisualElement element, int index) =>
                (element as Toggle).value = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).populated;
        }
    }
    
  5. В Unity выберите PlanetsMultiColumnTreeView.cs в окне Project.

  6. Перетащите PlanetsMultiColumnTreeView.uxml в поле Uxml в Inspector.

  7. Выберите Планеты > Многостороннее Дерево, чтобы увидеть список с двумя столбцами. Первый столбец содержит два списка планет, сгруппированных по узлам. Рядом с каждым узлом находится стрелка. Если вы выберете стрелку, окно покажет список планет и переключателей в этой группе.

Список в окне Unity Editor с двумя столбцами, одним для планет и одним с флагом, указывающим, населена ли планета. Кроме того, данные организованы в два горизонтальных раздела, называемых Внутренние Планеты и Внешние Планеты.
Список в окне Unity Editor с двумя столбцами, одним для планет и одним с флагом, указывающим, населена ли планета. Кроме того, данные организованы в два горизонтальных раздела, называемых Внутренние Планеты и Внешние Планеты.

Дополнительные ресурсы