Define custom control attributes for complex data types
Use attribute converter and UxmlObject to define UXML attributes for complex data types.
阅读时间4 分钟最后更新于 1 个月前
You can use attribute converters and UxmlObject to support complex data types attributes for your custom controls.
Attribute converters
Attribute converters convert a UxmlAttribute type to and from a string. It provides a set of built-in converters for common types, such as , , , , and . For complex data types, such as lists or custom classes, you need to create custom converters.
intfloatboolstringVector2The following C# code example creates a custom class called and a custom control class called . The class contains a field for the manager and a list of objects for the employees.
PersonDepartmentDepartmentPersonPersonusing 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; }}
If you edit the custom control in UI Builder, you get the following error message:
[UxmlElement] 'Department' has a [UxmlAttribute] 'manager' of an unknown type 'Person'. To fix this error, define a custom UxmlAttributeConverter<Person>.
To address this, create an attribute converter for the class that inherits from and implements the and methods to convert the object to and from a string. The following example creates a converter for the class:
PersonUxmlAttributeConverter<Person>ToStringFromStringPersonPersonusing 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; } }}
The converter combines the three values into a single string format, with the pattern of . The method splits the string into the three values and assigns them to the object.
[name]:[age]:[nationality]FromStringPersonThe following shows an example usage of the element in a UXML file:
Department<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
When using attribute converters, as data types become more intricate or when dealing with extensive lists, the generated strings can quickly grow convoluted and unwieldy. To simplify this, you can use .
UxmlObjectsUxmlObjectsTo understand how to use , take the previous and classes example, convert them into as shown in the following example:
UxmlObjectsPersonDepartmentUxmlObjectsusing 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; }}
The class now resembles a custom element, and uses for attribute declaration and introducing the UxmlObject attribute to signify its status as a .
PersonUxmlAttributeUxmlObjectInstead of using for fields, this example uses UxmlObjectReference to assign a . The name specifies the parent element of the .
UxmlAttributeUxmlObjectnameUxmlObjectPreviously, all were stored as direct children of the element, which caused scalability issues when multiple fields were present. It was difficult to distinguish which belonged to which field.
UxmlObjectsUxmlObjectUxmlObjectsThe attribute resolves this issue by specifying a name for the . This name corresponds to the UXML tag name. In the previous example, the and fields belong to the class. The attribute ensures that the class is correctly assigned to the and fields.
UxmlObjectReferenceUxmlObjectmanageremployeesPersonUxmlObjectReferencePersonmanageremployeesThe following shows an example usage in a UXML file:
<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>