Version: Unity 6.0 (6000.0)
语言 : 中文
绑定自定义控件
支持编辑器 UI

将自定义控件绑定到自定义数据类型

版本:2021.3+

此示例演示了如何将自定义控件绑定到自定义数据类型。

示例概述

此示例基于三个内置控件创建了自定义数据类型和自定义控件。它将自定义控件绑定到自定义数据类型。绘制器 (drawer) 可在摄氏度和华氏度之间转换。

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

先决条件

本指南适用于熟悉 Unity 编辑器、UI 工具包和 C# 脚本的开发者。在开始之前,请熟悉以下内容:

创建自定义数据类型

创建自定义数据类型 Temperature,并将其用作序列化属性。

  1. 使用任何模板创建 Unity 项目。

  2. 创建名为 bind-custom-data-type 的文件夹来存储所有文件。

  3. 创建一个名为 Temperature.cs 的 C# 脚本,并将其内容替换为以下代码:

    using System;
    
    namespace UIToolkitExamples
    {
        public enum TemperatureUnit
        {
            Celsius,
            Farenheit
        }
    
        [Serializable]
        public struct Temperature
        {
            public double value;
            public TemperatureUnit unit;
        }
    }
    
  4. 创建一个名为 PlanetScript.cs 的 C# 脚本,并将其内容替换为以下代码:

    using UnityEngine;
    
    namespace UIToolkitExamples
    {
        public class PlanetScript : MonoBehaviour
        {
            public Temperature coreTemperature;
        }
    }
    

创建自定义控件

Planet 创建自定义编辑器,为 Temperature 创建自定义属性绘制器 (Property Drawer)。

在自定义属性绘制器中,通过写入 SerializedProperty 的属性(使用 doubleValueenumValueIndex),然后调用 SerializedObject.ApplyModifiedProperties(),实现在华氏温度和摄氏温度之间转换温度的按钮。

自定义属性 Draweris 被视为自定义控件。这是一个以自定义方式行事的内置控件。

  1. 创建一个名为 Editor 的文件夹。

  2. Editor 文件夹中创建一个名为 PlanetEditor.cs 的 C# 脚本,并将其内容替换为以下代码:

    using UnityEditor;
    using UnityEngine.UIElements;
    using UnityEditor.UIElements;
    
    namespace UIToolkitExamples
    {
        [CustomEditor(typeof(PlanetScript))]
        public class PlanetEditor : Editor
        {
            public override VisualElement CreateInspectorGUI()
            {
                return new PropertyField(serializedObject.FindProperty("coreTemperature"));
            }
        }
    }
    
  3. Editor 文件夹中创建一个名为 TemperatureDrawer.cs 的 C# 脚本,并将其内容替换为以下代码:

    using UnityEditor;
    using UnityEngine;
    using UnityEngine.UIElements;
    
    namespace UIToolkitExamples
    {
        [CustomPropertyDrawer(typeof(Temperature))]
        public class TemperatureDrawer : PropertyDrawer
        {
            public override VisualElement CreatePropertyGUI(SerializedProperty property)
            {
                var asset = Resources.Load<VisualTreeAsset>("temperature_drawer");
                var drawer = asset.Instantiate(property.propertyPath);
    
                drawer.Q<Label>().text = property.displayName;
    
                // Don't allow conversion when you've selected multiple objects in the Inspector
                if (!property.serializedObject.isEditingMultipleObjects)
                {
                    drawer.Q<Button>().RegisterCallback<ClickEvent, SerializedProperty>(Convert, property);
                }
    
                return drawer;
            }
    
            static void Convert(ClickEvent evt, SerializedProperty property)
            {
                var valueProperty = property.FindPropertyRelative("value");
                var unitProperty = property.FindPropertyRelative("unit");
    
                // F -> C
                if (unitProperty.enumValueIndex == (int)TemperatureUnit.Farenheit)
                {
                    valueProperty.doubleValue -= 32;
                    valueProperty.doubleValue *= 5.0d / 9.0d;
                    unitProperty.enumValueIndex = (int)TemperatureUnit.Celsius;
                }
                else // C -> F
                {
                    valueProperty.doubleValue *= 9.0d / 5.0d;
                    valueProperty.doubleValue += 32;
                    unitProperty.enumValueIndex = (int)TemperatureUnit.Farenheit;
                }
    
                // Important: Because you are bypassing the binding system, you must save the modified SerializedObject
                property.serializedObject.ApplyModifiedProperties();
            }
        }
    }
    

设置绑定

创建具有以下元素的 UXML 文件:

  • DoubleField
  • EnumField
  • Button

将两个字段的 binding-path 设置为 Temperature 属性的 valueunit

  1. Editor 文件夹中,创建一个名为 Resources 的文件夹。

  2. Resources 文件夹中,创建一个名为 temperature_drawer.uxml__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
    See in Glossary
    文档,并将其内容替换为以下内容:

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:VisualElement class="unity-base-field">
            <ui:Label class="unity-base-field__label" />
            <ui:VisualElement class="unity-base-field__input" style="flex-direction: row;">
                <uie:DoubleField binding-path="value" />
                <uie:EnumField binding-path="unit" />
                <ui:Button text="Convert" />
            </ui:VisualElement>
        </ui:VisualElement>
    </ui:UXML>
    

测试绑定

  1. 在场景中创建空游戏对象。
  2. 在层级视图 (Hierarchy) 中选择游戏对象。
  3. PlanetScript.cs 拖到检视面板 (Inspector) 上。这会向游戏对象添加一个 Planet Script 组件。
  4. Temperature 字段中输入一个数字,然后从下拉选单中选择单位。
  5. 选择转换 (Convert) 按钮可在单位之间进行转换。如果在 Inspector UI 中作出更改,则自定义控件的 Temperature 属性会更改。

其他资源

绑定自定义控件
支持编辑器 UI