Version: Unity 6.0 (6000.0)
语言 : 中文
SerializedObject 数据绑定
可绑定元素参考

SerializedObject 数据绑定简介

您可以使用 SerializedObject 数据绑定系统绑定到序列化属性。这意味着可以将视觉元素绑定到与序列化系统兼容的以下对象:

  • 用户定义的 ScriptableObject 类
  • 用户定义的 MonoBehaviour 类
  • Unity 原生组件类型
  • Unity 原生资源类型
  • 原始 C# 类型,例如 int、bool 或 float。
  • 原生 Unity 类型,例如 Vector3、Color 或 Object。

值绑定

仅能绑定可实现 INotifyValueChanged 接口的视觉元素的 value 属性。例如,可以将 TextField.value 绑定到 string,但不能将 TextField.name 绑定到 string。

可以在对象与派生自 BindableElement 或实现 IBindable 接口的任何视觉元素之间进行绑定。

创建绑定

要创建绑定,请调用 Bind() 或 BindProperty()。

调用 Bind()

您可以调用 Bind() 将元素绑定到 SerializedObject。在绑定元素之前,必须设置绑定路径并创建 SerializedObject。

如果您不方便访问用于绑定的 SerializedProperty,请使用此方法。相关示例,请参阅使用 C# 脚本创建绑定。

Bind() 扩展方法使用指定的 bindingPath 属性设置视觉元素的整个层级视图。可以在单个元素或要绑定的层级视图的父级上调用 Bind() 方法。例如,可以在 Editor 窗口的 rootVisualElement 上调用 Bind()。这会绑定具有指定 bindingPath 属性的所有子元素。

请勿从 Editor.CreateInspectorGUI() 或 PropertyDrawer.CreatePropertyGUI() 覆盖中调用 Bind()。这些覆盖会在这些方法返回的视觉元素上自动调用。

调用 Unbind()

Unbind() 方法会停止对该元素及其所有直接和间接子元素的值跟踪。通常,无需调用 Unbind(),因为当用户关闭 Inspector 或 Editor 窗口时,跟踪会停止。如果必须在元素生命周期中将元素绑定到不同目标,请调用 Unbind()。

如果在 C# 中通过调用其构造函数来构造 InspectorElement,则会在构造函数调用期间发生绑定操作。如果要在构建 InspectorElement 后进行绑定,则必须调用 Unbind(),然后显式调用 Bind(),或者让父级的绑定操作来创建绑定。

设置绑定路径

如果调用 Bind() 来创建绑定,必须将视觉元素的绑定路径设置为要绑定到的对象的属性名称。

例如:

  • 如果您有以下组件脚本:

    using UnityEngine;
    
    public class MyComp : MonoBehaviour
    {
        [SerializeField]
        int m_Count;
    }
    

    要将视觉元素绑定到 m_Count,请将绑定路径设置为 m_Count。

  • 如果要将视觉元素绑定到游戏对象的名称属性(即 m_Name),请将绑定路径设置为 m_Name。

您可以在__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
See in Glossary
Builder、UXML 中或使用 C# 脚本设置绑定路径:

调用 BindProperty()

您可以调用 BindProperty() 将元素直接绑定到 SerializedProperty。

如果已有 SerializedProperty 对象,尤其是为了动态构建 UI 而遍历 SerializedObject 的属性,请使用此方法。相关示例,请参阅不使用绑定路径进行绑定。

将元素绑定到嵌套属性

可以将视觉元素绑定到源对象中的嵌套属性。为此,请将元素的绑定路径与第一个祖先元素的绑定路径相结合。将此方法与以下元素结合使用:

相关示例,请参阅绑定到嵌套属性。

当值更改时接收回调

您可以创建一个绑定以便在绑定的序列化属性发生更改时接收回调。为此,请利用 TrackPropertyValue() 扩展方法(任何 VisualElement 都可以使用此方法)。这会注册在提供的 SerializedProperty 发生更改时执行的回调。相关示例,请参阅序列化属性发生更改时接收回调。

还可以创建一个绑定以便在已绑定序列化对象的任何属性发生更改时接收回调。为此,请利用 TrackSerializedObjectValue() 扩展方法(任何 VisualElement 都可以使用此方法)。这会注册在提供的 SerializedProperty 发生更改时执行的回调。相关示例,请参阅任何属性发生更改时接收回调。

绑定自定义元素

您可以通过值绑定系统创建自定义元素并将其绑定到序列化属性。

要创建可绑定的自定义元素:

  1. 声明自定义元素。
  2. 让元素继承自 BindableElement 或实现 IBinding 接口。
  3. 实现 INotifyValueChanged 接口。
  4. 为 INotifyValueChanged 接口实现 SetValueWithoutNotify() 方法。
  5. 为 INotifyValueChanged 接口实现 value 属性访问器。

相关示例,请参阅创建自定义控件并设置样式。

注意:无法将自定义数据类型直接绑定到自定义元素,因为绑定系统只允许将元素绑定到 enum 的SerializedPropertyType 支持的类型。这意味着无法定义类或结构,例如,名为 MyStruct 的结构,也无法将其绑定到一个实现 INotifyValueChanged<MyStruct> 的元素。但是,可以绑定到自定义数据类型的可序列化嵌套属性。这包括多态序列化(当字段使用 [SerializeReference] 属性时)。相关示例,请参阅将自定义控件绑定到自定义数据类型。

最佳实践

根据创建的 UI 类型,绑定发生在不同时间。这被称为绑定时间。

下表说明了控件的绑定时间:

条件 自动绑定时间(假设设置了绑定路径)
用 C# 构造的 InspectorElement 在构造函数调用期间
当 CreateInspectorGUI() 或 CreatePropertyGUI() 这些方法返回时,位于其返回值之下的子元素 在 CreateInspectorGUI() 或 CreatePropertyGUI() 返回后
在父元素上调用 Bind() 或 BindProperty() 时位于元素下的子元素 在 Bind() 或 BindProperty() 调用期间
其他 无自动绑定;必须手动绑定元素或其父项之一

以下是创建绑定时有关绑定时间的最佳做法:

  • 如果创建自定义 Editor 或自定义 PropertyDrawer,那么在 CreateInspectorGUI() 体或 CreatePropertyGUI() 主体结束前,请设置元素的绑定路径,而不是对视觉树中的任何视觉元素调用 Bind() 或 BindProperty()。这些元素会在 CreateInspectorGUI() 或 CreatePropertyGUI() 返回后自动绑定。但是,如果在此点之后向视觉树添加任何元素,请调用 Bind() 或 BindProperty() 进行绑定。
  • 如果创建任何其他类型的 UI,请调用 Bind() 或 BindProperty(),无论元素何时添加到视觉树中。如果同时调用 Bind() 或 BindProperty() 并绑定多个控件,请设置每个控件的绑定路径,然后调用包含所有控件的最低级别父元素的 Bind()。如果 Bind() 所调用的元素有绑定路径,那么它会绑定该元素;并且如果该元素的所有子元素都有绑定路径,那么它会以递归方式绑定所有子元素。为防止对性能产生负面影响,请勿多次使用 Bind() 方法绑定同一个视觉元素。

绑定示例

请尝试以下示例,了解如何利用数据绑定编写代码:

其他资源

SerializedObject 数据绑定
可绑定元素参考