版本:Unity 6 (6000.0)
语言:英语
无需 ListView 绑定到列表
将自定义控件绑定到自定义数据类型

绑定自定义控件

版本: 2021.3+

此示例演示如何将自定义控件绑定到原生 Unity 类型。

示例概述

该示例创建了一个自定义控件,用于显示 2D 图像。它在自定义编辑器中使用自定义控件,用于新的资产类型,并将自定义控件绑定到新类型资产中的字段。

您可以在此 GitHub 存储库 中找到此示例创建的完整文件。

先决条件

本指南适用于熟悉 Unity 编辑器、UI(用户界面) 允许用户与您的应用程序进行交互。Unity 目前支持三种 UI 系统。 更多信息
请参阅 术语表
工具包和 C# 脚本的开发人员。在开始之前,请先熟悉以下内容

创建序列化对象

创建包含 Texture2D 的序列化对象。

  1. 使用任何模板创建一个 Unity 项目。
  2. 项目窗口显示 Assets 文件夹内容的窗口(项目选项卡) 更多信息
    请参阅 术语表
    中,创建一个名为 bind-custom-control 的文件夹来存储文件。
  3. 创建一个名为 TextureAsset.cs 的 C# 脚本,并将它的内容替换为以下内容
using UnityEngine;

namespace UIToolkitExamples
{
    [CreateAssetMenu(menuName = "UIToolkitExamples/TextureAsset")]
    public class TextureAsset : ScriptableObject
    {
        public Texture2D texture;

        public void Reset()
        {
            texture = null;
        }
    }
}

创建和设置自定义控件的样式

使用 C# 创建一个自定义控件,该控件代表对 2D 纹理资产的引用,并使用 USS 为其设置样式。

  1. 在该文件夹中,创建一个名为 Editor 的文件夹。
  2. Editor 文件夹中,创建一个名为 TexturePreviewElement.cs 的 C# 脚本。
  3. TexturePreviewElement.cs 的内容替换为以下内容
using System;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;

namespace UIToolkitExamples
{
    [UxmlElement]
    public partial class TexturePreviewElement : BindableElement, INotifyValueChanged<Object>
    {
        public static readonly string ussClassName = "texture-preview-element";

        Image m_Preview;
        ObjectField m_ObjectField;
        Texture2D m_Value;

        public TexturePreviewElement()
        {
            AddToClassList(ussClassName);

            // Create a preview image.
            m_Preview = new Image();
            Add(m_Preview);

            // Create an ObjectField, set its object type, and register a callback when its value changes.
            m_ObjectField = new ObjectField();
            m_ObjectField.objectType = typeof(Texture2D);
            m_ObjectField.RegisterValueChangedCallback(OnObjectFieldValueChanged);
            Add(m_ObjectField);

            styleSheets.Add(Resources.Load<StyleSheet>("texture_preview_element"));
        }
        
        void OnObjectFieldValueChanged(ChangeEvent<Object> evt)
        {
            value = evt.newValue;
        }

        public void SetValueWithoutNotify(Object newValue)
        {
            if (newValue == null || newValue is Texture2D)
            {
                // Update the preview Image and update the ObjectField.
                m_Value = newValue as Texture2D;
                m_Preview.image = m_Value;
                // Notice that this line calls the ObjectField's SetValueWithoutNotify() method instead of just setting
                // m_ObjectField.value. This is very important; you don't want m_ObjectField to send a ChangeEvent.
                m_ObjectField.SetValueWithoutNotify(m_Value);
            }
            else throw new ArgumentException($"Expected object of type {typeof(Texture2D)}");
        }

        public Object value
        {
            get => m_Value;
            // The setter is called when the user changes the value of the ObjectField, which calls
            // OnObjectFieldValueChanged(), which calls this.
            set
            {
                if (value == this.value)
                    return;

                var previous = this.value;
                SetValueWithoutNotify(value);

                using (var evt = ChangeEvent<Object>.GetPooled(previous, value))
                {
                    evt.target = this;
                    SendEvent(evt);
                }
            }
        }
    }
}
  1. Editor 文件夹中,创建一个名为 Resources 的文件夹。
  2. Resources 文件夹中,创建一个名为 texture_preview_element.uss 的样式表,并将它的内容替换为以下内容
.texture-preview-element {
    width: 200px;
    height: 200px;
}

.texture-preview-element > .unity-image {
    flex-grow: 1;
}

创建检查器 UI

创建 检查器一个 Unity 窗口,显示当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。 更多信息
请参阅 术语表
UI,并将自定义控件绑定到 Texture2D 对象。

  1. Editor 文件夹中,创建一个名为 TextureAssetEditor.cs 的 C# 脚本,并将它的内容替换为以下内容
using UnityEditor;
using UnityEngine.UIElements;
using UnityEngine;

namespace UIToolkitExamples
{
    [CustomEditor(typeof(TextureAsset))]
    public class TextureAssetEditor : Editor
    {
        [SerializeField]
        VisualTreeAsset m_VisualTree;

        public override VisualElement CreateInspectorGUI()
        {
            return m_VisualTree.CloneTree();
        }
    }
}

使用 UXML 设置绑定

创建一个包含 TexturePreviewElement 的 UXML 文件,并将 binding-path 属性设置为 texture。这将 TexturePreviewElement 绑定到 TextureAsset.texture

  1. Editor 文件夹中,创建一个名为 texture_asset_editor.uxml 的 UI 文档,并将它的内容替换为以下内容
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:example="UIToolkitExamples" editor-extension-mode="True">
    <example:TexturePreviewElement binding-path="texture" />
</ui:UXML>
  1. 在项目窗口中,选择 TextureAssetEditor.cs
  2. texture_asset_editor.uxml 拖到检查器中的 可视化树

测试绑定

  1. 从菜单中,选择 Assets > Create > UIToolkitExamples > TextureAsset。这将创建一个 TextureAsset 的实例。
  2. 选择新的 TextureAsset 对象。在 检查器 中,您可以看到 Texture Preview Element。如果您将纹理资产引用放到该字段中,您将在该字段上方看到预览。如果您在 UI 中更改 Texture Preview Element 中的资产引用,TextureAsset.texture 将发生改变。

其他资源

无需 ListView 绑定到列表
将自定义控件绑定到自定义数据类型