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

Определение пользовательских атрибутов управления для сложных типов данных

Вы можете использовать конвертер атрибутов и UxmlObject для поддержки сложных атрибутов типов данных для ваших пользовательских контроллеров.

Преобразователи атрибутов

Преобразователи атрибутов конвертировать UxmlAttribute типа в строку и из строки. Он предоставляет набор встроенные преобразователи для общих типов, таких как int, float, bool, string, и Vector2. Для сложных типов данных, таких как списки или пользовательские классы, необходимо создать пользовательские конвертер.

В следующем примере кода C# создаётся пользовательский класс с именем Person и класс пользовательского элемента управления с именем Department. Department класс содержит Person поле для менеджера и перечень Person объекты для работников.

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace AttributeConverterExample
{
    [Serializable]
    public class Person
    {
        public string name;
        public int age;
        public string nationality;
    }

    [UxmlElement]
    public partial class Department : VisualElement
    {
        [UxmlAttribute]
        public Person manager;

        [UxmlAttribute]
        public List<Person> employees;
    }
}

При изменении пользовательского элемента управления в UI Builder, вы получаете следующее сообщение об ошибке:

[UxmlElement] 'Department' has a [UxmlAttribute] 'manager' of an unknown type 'Person'. To fix this error, define a custom UxmlAttributeConverter<Person>.

Для решения этой проблемы создайте конвертер атрибутов для Person класс, который наследуется от UxmlAttributeConverter<Person> и осуществляет ToString и FromString методы для преобразования Person В следующем примере создается конвертер для объекта, который может быть Person class:


using UnityEditor.UIElements;

namespace AttributeConverterExample
{
    public class PersonConverter : UxmlAttributeConverter<Person>
    {
        const char k_Separator = ':';

        public override string ToString(Person value)
        {
            return $"{value.name}{k_Separator}{value.age}{k_Separator}{value.nationality}";
        }

        public override Person FromString(string value)
        {
            var person = new Person();
            var split = value.Split(k_Separator);
            if (split.Length == 3)
            {
                person.name = split[0];
                person.age = int.Parse(split[1]);
                person.nationality = split[2];
            }
            return person;
        }
    }
}

Преобразователь объединяет три значения в одну строку по шаблону [name]:[age]:[nationality]. Метод FromString разделяет строку на три значения и присваивает их объекту Person.

Ниже приведен пример использования элемента Department в файле UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <AttributeConverterExample.Department name="Dunder Mifflin" manager="Michael Scott:58:USA" employees="Dwight Schrute:53:USA,Jim Halpert:44:USA" />
</ui:UXML>

UxmlObjects

При использовании преобразователей атрибутов, по мере того как типы данных становятся более сложными или при работе с обширными списками, генерируемые строки могут быстро стать запутанными и громоздкими. Чтобы упростить это, вы можете использовать UxmlObjects.

,UxmlObjects, являются классами, инстанционированными из UXML, которые содержат атрибуты UXML.

Чтобы понять, как использовать UxmlObjects, возьмите предыдущие примеры классов Person и Department, преобразуйте их в UxmlObjects, как показано в следующем примере:

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace UxmlObjectExample
{
    [UxmlObject]
    public partial class Person
    {
        [UxmlAttribute]
        public string name;

        [UxmlAttribute]
        public int age;

        [UxmlAttribute]
        public string nationality;
    }

    [UxmlElement]
    public partial class Department : VisualElement
    {
        [UxmlObjectReference("manager")]
        public Person manager;

        [UxmlObjectReference("employees")]
        public List<Person> employees;
    }
}

Person класс теперь напоминает пользовательский элемент и использует UxmlAttribute для объявления атрибутов и введение UxmlObject атрибут, указывающий на его статус в качестве UxmlObject.

Вместо использования UxmlAttribute для полей UxmlObject, в этом примере используются UxmlObjectReference для назначения name. Имя указывает родительский элемент UxmlObject.

Раньше все UxmlObjects хранились как прямые дочери элемента, что вызывало проблемы масштабируемости при наличии нескольких полей UxmlObject. Было трудно определить, какое UxmlObjects принадлежит к какому полю.

UxmlObjectReference атрибут решает эту проблему, указывая имя для UxmlObject. Это название соответствует UXML имя тега. В предыдущем примере manager и employees поля принадлежат Person class. The UxmlObjectReference атрибут обеспечивает, что Person класс корректно назначен manager и employees полевых исследований.

Ниже приведен пример использования в файле UXML:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <UxmlObjectExample.Department name="Department One">
        <manager>
            <UxmlObjectExample.Person name="Manager One" age="58" nationality="Canadian" />
        </manager>
        <employees>
            <UxmlObjectExample.Person name="Person Two" age="53" nationality="Canadian" />
            <UxmlObjectExample.Person name="Person Three" age="44" nationality="Canadian" />
        </employees>
    </UxmlObjectExample.Department>
</ui:UXML>

Примечание: UxmlObjectReferenceFields также работает с интерфейсами. Однако, вы можете назначить только UxmlObjects которые реализуют указанный интерфейс. Пример работы с интерфейсами см. в UxmlObjectReferenceAttribute.

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