版本:Unity 6 (6000.0)
语言:英语
创建自定义控件
将自定义控件绑定到数据

自定义 UXML 标签名称和属性

您可以在 UI(用户界面) 允许用户与您的应用程序进行交互。Unity 目前支持三种 UI 系统。 更多信息
参见 词汇表
Builder 中自定义 UXML 标签名称、为自定义控件创建自定义属性以及添加属性修饰符。

自定义自定义控件名称

默认情况下,UXML 中自定义控件的标签名称是 C# 类名。不建议标签名称与 C# 类名不同。但是,您可以选择自定义标签名称。

要自定义 UXML 标签名称,请将 name 参数添加到 UxmlElement 属性中。

注意:标签名称必须是唯一的,并且您必须在 UXML 中引用类的命名空间。

例如,如果您创建以下自定义按钮

using UnityEngine.UIElements;

[UxmlElement("MyButton")]
public partial class CustomButtonElement : Button
{
}

然后,您可以在 UXML 中使用自定义名称或其类型引用自定义按钮

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <MyButton />
    <CustomButtonElement />
</ui:UXML>

为自定义控件创建自定义属性

要为自定义控件创建新属性,请将 UxmlAttribute 属性添加到自定义属性定义中。默认情况下,UI 工具包会将 C# 驼峰式或帕斯卡式属性名称解析为由连字符连接的小写单词。例如,在 C# 中名为 MyFloatmyFloat 的属性在 UXML 和 UI Builder 中变为 my-float

创建简单的自定义属性

以下示例创建了一个具有多个自定义属性的自定义控件

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

[UxmlElement]
public partial class ExampleVisualElement : VisualElement
{
    [UxmlAttribute]
    public string myStringValue { get; set; }

    [UxmlAttribute]
    public int myIntValue { get; set; }

    [UxmlAttribute]
    public float myFloatValue { get; set; }

    [UxmlAttribute]
    public List<int> myListOfInts { get; set; }

    [UxmlAttribute, UxmlTypeReference(typeof(VisualElement))]
    public Type myType { get; set; }

    [UxmlAttribute]
    public Texture2D myTexture { get; set; }

    [UxmlAttribute]
    public Color myColor { get; set; }
}

以下示例 UXML 文档使用了自定义控件

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <ExampleElement my-string-value="Hello World" my-int-value="123" />
    <ExampleElement my-float-value="3.14" my-list-of-ints="1,2,3" />
    <ExampleElement my-string-value="Hello World" my-int-value="123" />
    <ExampleElement my-texture="project://database/Assets/MyTexture.png" />
    <ExampleElement my-color="#FF0000FF" />
    <ExampleElement my-type="UnityEngine.UIElements.Button, UnityEngine.UIElementsModule" />
</ui:UXML>

创建复杂的自定义属性

您可以将结构或类实例用作属性,并将结构或类实例的列表用作属性。为此,您必须将它们转换为字符串并从字符串转换为字符串,并声明一个 UxmlAttributeConverter 来支持此转换。

注意:当您在列表中使用类时,请确保其字符串表示不包含任何逗号 (,),因为逗号用于分隔项目。

以下示例创建了一个具有自定义列表属性的自定义控件

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

[Serializable]
public class MyClassWithData
{
    public int myInt;
    public float myFloat;
}

[UxmlElement]
public partial class MyElementWithData : VisualElement
{
    [UxmlAttribute]
    public MyClassWithData someData;

    [UxmlAttribute]
    public List<MyClassWithData> lotsOfData;
}

以下示例将自定义属性转换为字符串,并声明一个 UxmlAttributeConverter 来支持转换

using System;
using System.Globalization;
using UnityEditor.UIElements;

public class MyClassWithDataConverter : UxmlAttributeConverter<MyClassWithData>
{
    public override MyClassWithData FromString(string value)
    {
        // Split using a | so that comma (,) can be used by the list.
        var split = value.Split('|');

        return new MyClassWithData
        {
            myInt = int.Parse(split[0]),
            myFloat = float.Parse(split[1], CultureInfo.InvariantCulture)
        };
    }

    public override string ToString(MyClassWithData value) => FormattableString.Invariant($"{value.myInt}|{value.myFloat}");
}

以下示例 UXML 文档使用了自定义控件

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <MyElementWithData some-data="1|2.3" lots-of-data="1|2,3|4,5|6" />
</ui:UXML>

使用 UxmlObjectReference 创建嵌套的自定义属性

您可以使用 UxmlObjectReference 来创建嵌套的自定义属性。为此,您使用 UxmlObjectReference 属性来设置一个名称。此名称表示 UxmlObjects 将作为父级添加到具有该名称的元素中。这有助于您在元素中管理 UxmlObjects,尤其是在元素具有多个 UxmlObject 字段时。通过将 UxmlObjects 分配给 UxmlObjectReference 中的特定名称,您可以轻松地了解哪些 UxmlObjects 属于哪个字段,从而使您的项目更清晰、更井井有条。

有关更多信息和示例,请参见 UxmlObjectReferenceAttribute

自定义自定义属性名称

您可以通过 UxmlAttribute 属性的 name 参数来自定义属性名称。

以下示例创建了一个具有自定义属性名称的自定义控件

using UnityEngine.UIElements;

[UxmlElement]
public partial class CustomAttributeNameExample : VisualElement
{
    [UxmlAttribute("character-name")]
    public string myStringValue { get; set; }

    [UxmlAttribute("credits")]
    public float myFloatValue { get; set; }

    [UxmlAttribute("level")]
    public int myIntValue { get; set; }

    [UxmlAttribute("usage")]
    public UsageHints myEnumValue { get; set; }
}

以下示例 UXML 文档使用了自定义属性名称

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <CustomAttributeNameExample character-name="Karl" credits="1.23" level="1" usage="DynamicColor" />
</ui:UXML>

如果您更改了属性的名称,为了确保使用旧属性名称的 UXML 文件仍然可以使用,请将 obsoleteNames 参数添加到 UxmlAttribute 属性中。

以下示例创建了一个具有自定义和已弃用属性名称的自定义控件

using UnityEngine.UIElements;

[UxmlElement]
public partial class CharacterDetails : VisualElement
{
    [UxmlAttribute("character-name", "npc-name")]
    public string npcName { get; set; }

    [UxmlAttribute("character-health", "health")]
    public float health { get; set; }
}

以下示例 UXML 文档使用了已弃用的名称

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <CharacterDetails npc-name="Haydee" health="100" />
</ui:UXML>

在 UI Builder 中添加属性修饰符

您可以在自定义属性字段上添加以下修饰符属性。当您添加修饰符属性时,相应的 UI 控件(例如 Range 的滑块)会显示在 UI Builder 的 Inspector一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。 更多信息
参见 词汇表
选项卡中

以下示例创建了一个在其属性字段上带有修饰符的自定义控件

using UnityEngine.UIElements;
using UnityEngine;

[UxmlElement]
public partial class ExampleText : VisualElement
{
    [TextArea, UxmlAttribute]
    public string myText;

    [Header("My Header")]
    [Range(0, 100)]
    [UxmlAttribute]
    public int rangedInt;

    [Tooltip("My custom tooltip")]
    [Min(10)]
    [UxmlAttribute]
    public int minValue = 100;
}

UI Builder 将显示带有修饰符的属性

Attributes with the decorators
带有修饰符的属性

在 UI Builder 中添加自定义属性绘制器

您可以在 UI Builder 中的字段上添加 自定义属性绘制器

以下示例创建了一个具有自定义 属性绘制器一个 Unity 功能,允许您通过在脚本中使用属性或通过控制特定可序列化类的外观来自定义 Inspector 窗口中某些控件的外观。 更多信息
参见 词汇表

using UnityEngine;
using UnityEngine.UIElements;

public class MyDrawerAttribute : PropertyAttribute { }

[UxmlElement]
public partial class MyDrawerExample : Button
{
    [UxmlAttribute]
    public Color myColor;

    [MyDrawer, UxmlAttribute]
    public string myText;
}

要访问其他序列化属性,请在名称前加上 serializedData。以下代码示例使用 serializedData.myColor 来查找 myColor 属性

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

[CustomPropertyDrawer(typeof(MyDrawerAttribute))]
public class MyDrawerAttributePropertyDrawer : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        var row = new VisualElement { style = { flexDirection = FlexDirection.Row } };
        var textField = new TextField("My Text") { style = { flexGrow = 1 } };
        var button = new Button { text = ":" };
        button.clicked += () => textField.value = "RESET";

        // Get the parent property
        var parentPropertyPath = property.propertyPath.Substring(0, property.propertyPath.LastIndexOf('.'));
        var parent = property.serializedObject.FindProperty(parentPropertyPath);

        var colorProp = parent.FindPropertyRelative("myColor");
        textField.TrackPropertyValue(colorProp, p =>
        {
            row.style.backgroundColor = p.colorValue;
        });

        row.style.backgroundColor = colorProp.colorValue;
        row.Add(textField);
        row.Add(button);
        textField.BindProperty(property);

        return row;
    }
}

自定义属性绘制器如下所示

Custom property drawer with a color picker
带有颜色选择器的自定义属性绘制器

其他资源

创建自定义控件
将自定义控件绑定到数据