Version: 6000.3
语言: 中文
绑定自定义控件
支持编辑器UI

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

版本: 2021.3+

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

示例概述

此示例基于三个内置控件创建自定义数据类型和自定义控件。它将自定义控件绑定到自定义数据类型。抽屉在摄氏度和华氏度之间转换。

带有转换温度的自定义控件的脚本,显示在 Unity 编辑器中。
带有转换温度的自定义控件的脚本,显示在 Unity 编辑器中。

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

先决条件

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

创建自定义数据类型

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

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

  2. 创建一个名为bind-custom-data-type以存储所有文件。

  3. 创建名为Temperature.cs并将其内容替换为以下内容:

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

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

创建自定义控件

创建自定义编辑器Planet和一个自定义属性抽屉一种 Unity 功能,允许你使用脚本上的属性,或通过控制特定 Serializable 类的外观来自定义检查器窗口中某些控件的外观 更多信息
请参阅术语表
Temperature.

在自定义属性抽屉中,实现一个按钮,通过写入SerializedProperty(使用doubleValueenumValueIndex),然后调用SerializedObject.ApplyModifiedProperties().

自定义属性抽屉被视为自定义控件。它是一个以自定义方式运行的内置控件。

  1. 创建一个名为Editor.

  2. Editor 文件夹中,创建一个名为PlanetEditor.cs并将其内容替换为以下内容:

    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并将其内容替换为以下内容:

    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文件:

  • 双字段
  • 枚举字段
  • 一个按钮

binding-path将两个字段的valueunitTemperature财产。

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

  2. Resources 文件夹中,创建一个名为temperature_drawer.uxml并将其内容替换为以下内容:

    <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. 创建一个空的游戏对象Unity 场景中的基本对象,可以表示角色、道具、风景、相机、航路点等。游戏对象的功能由附加到它的组件定义。更多信息
    请参阅术语表
    场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
    请参阅术语表
    .
  2. 在“层次结构”中,选择“游戏对象”。
  3. PlanetScript.cs拖到检查器一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息
    请参阅术语表
    . 这会向游戏对象添加一个 Planet Script 组件。
  4. 温度字段中输入一个数字,然后从下拉列表中选择一个单位。
  5. 选择 Convert 按钮以在单位之间进行转换。如果您在 Inspector UI 中进行更改,则Temperature自定义控制更改的属性。

其他资源

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