版本:Unity 6 (6000.0)
语言:English
自定义控件
自定义 UXML 标签名称和属性

创建自定义控件

一个好的自定义控件是抽象的、自包含的和重复出现的。

一个滑块切换是自定义控件的一个很好的例子

  • 它是抽象的。您可以使用它在一种设置和另一种设置之间切换。
  • 它是自包含的。您为它提供一个标签和一个初始值。当滑块切换的状态发生变化时,它会触发一个事件。
  • 它是重复出现的。您可以在应用程序的多个位置使用它。

应用程序的菜单栏不是自定义控件的一个好例子

  • 它不是抽象的。它特定于您的应用程序。
  • 它不是自包含的。它可能依赖于应用程序的其他部分。
  • 它不是重复出现的。您的应用程序中可能只有一个菜单。

创建自定义控件后,您可以使用 USS 为其设置样式,并添加 C# 代码来处理事件。

创建和使用自定义控件

要创建自定义控件,请执行以下操作

  • UxmlElement 属性添加到自定义控件类定义中。
  • 将自定义控件类声明为部分类。
  • VisualElement 或其派生类之一继承。

例如

using UnityEngine;
using UnityEngine.UIElements;

[UxmlElement]
public partial class ExampleElement : VisualElement {}

创建自定义控件后,您可以在 UXML 和UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三种 UI 系统。 更多信息
参见 术语表
Builder 中使用它们。

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

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

默认情况下,自定义控件显示在 UI Builder 的库选项卡中。如果您想将其从库选项卡中隐藏,请添加HideInInspector 属性。

初始化自定义控件

自定义控件继承自 VisualElementVisualElement 未绑定到GameObjectUnity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等。GameObject 的功能由附加到它的组件定义。 更多信息
参见 术语表
的生命周期,并且不会接收任何这些回调

  • Awake()
  • OnEnable()
  • OnDisable()
  • OnDestroy()

您可以在自定义控件的构造函数中初始化它。但是,如果您的应用程序需要它,您可以延迟初始化,直到自定义控件添加到 UI 中。为此,请为AttachToPanelEvent 注册一个回调。要检测自定义控件已从 UI 中移除,请使用DetachFromPanelEvent 回调。

public CustomControl()
{
    var myCustomElement = rootVisualElement.Q(className: "my-custom-element");
    myCustomElement.RegisterCallback<AttachToPanelEvent>(e =>
        { /* do something here when element is added to UI */ });
    myCustomElement.RegisterCallback<DetachFromPanelEvent>(e =>
        { /* do something here when element is removed from UI */ });
}

UI 工具包为所有元素分派这两个事件,并且不需要自定义 VisualElement 子类。有关更多信息,请参阅面板事件

使用 USS 设置自定义控件的样式

使用 USS 自定义自定义控件的外观,就像内置控件一样。您还可以创建USS 自定义属性 来设置自定义控件的样式。

注意:UI Builder 中的InspectorUnity 窗口,显示当前选定 GameObject、资产或项目设置的信息,允许您检查和编辑值。 更多信息
参见 术语表
窗口不显示 USS 自定义属性。要编辑 USS 自定义属性,请使用文本编辑器直接编辑 USS 文件。

要在 C# 中与自定义控件的自定义 USS 属性交互,请使用CustomStyleProperty 结构和CustomStylesResolvedEvent 事件。

CustomStyleProperty 描述了您从样式表中读取的属性的名称和类型。

UI 工具包为直接接收自定义 USS 属性的任何元素分派CustomStylesResolvedEvent。它为任何元素分派事件,这些元素与选择器匹配,对于规则包含自定义属性值的那些选择器。UI 工具包不会为继承该值的元素分派事件。该事件保存对ICustomStyle 对象的引用。您必须使用其TryGetValue() 方法来读取CustomStyleProperty 的有效值。此方法具有针对不同类型CustomStyleProperty 的重载。

有关自定义样式和自定义控件示例,请参阅为自定义控件创建自定义样式

注意:您不能为自定义样式属性定义过渡。

处理自定义控件的事件

有关如何处理自定义控件事件的详细信息,请参阅处理事件

注意:

  • Unity 将键盘事件分派到当前获得焦点的元素。要处理自定义控件的键盘事件,请设置与 focus 相关的属性。
  • 要处理触摸和鼠标输入事件,请在构造函数中为相关的事件类型(例如指针事件鼠标事件)注册回调。

最佳实践和技巧

  • 将自定义控件表示的属性及其行为的其他功能方面公开为 UXML 属性,并将影响自定义控件外观的属性公开为 USS 属性。

  • 使用唯一、简短且可读的命名空间,以避免与其他元素发生名称冲突当物理引擎检测到两个 GameObject 的碰撞体发生接触或重叠时,就会发生碰撞,前提是至少有一个具有 Rigidbody 组件并且正在运动。 更多信息
    参见 术语表

  • 保持 UXML 属性为基本类型。您可以在 UXML 中指定的 数据仅限于一组基本数据类型。UXML 不支持复杂的数据结构或集合。通过 C#脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性并以您喜欢的任何方式响应用户输入。 更多信息
    参见 术语表
    或数据绑定在运行时将复杂数据传递给您的自定义控件,而不是在 UXML 中。

  • 在 C# 中,将 USS 类或名称公开为常量。这允许您使用UQuery 通过类或名称定位元素。

  • 为 USS 类采用BEM 标准。这允许您使用类列表选择器来处理每个元素。

  • 使用静态回调以降低内存占用。当您注册一个实例方法用作回调时,您可能会创建不必要的分配。为了避免分配,请使用匿名静态 lambda 函数调用常规 C# 静态方法。您可以通过EventBase.currentTarget 属性检索当前元素的上下文。

  • 通过自定义控件的generateVisualContent 回调渲染自定义几何图形。有关渲染部分填充圆圈的示例用法,请参阅RadialProgress 示例

  • 自定义控件很方便。但是,您可能可以通过以下方法获得相同的结果

    • 从现有元素组装您的 UI,并更改其样式和属性。
    • 使用 UXML 模板。使用常规 C# MonoBehaviour 添加与包含 UI 的特定 UI 文档相关的逻辑。(要了解如何使用 MonoBehaviour 控制 UI 文档中的 UI,请参阅创建第一个运行时 UI。)为了实现封装,在您的 MonoBehaviour 中创建属性和方法,这些属性和方法在内部使用UQuery 获取VisualElement 并操作其属性。

其他资源

自定义控件
自定义 UXML 标签名称和属性