Привязка настраиваемого контроля к настраиваемому типу данных
Версия: 2021.3+
В этом примере показано, как связать пользовательские элементы управления с пользовательскими типами данных.
Примерный обзор
В этом примере создается пользовательский тип данных и пользовательский контроллер, основанный на трех встроенных контроллерах. Он привязывает пользовательский контроллер к пользовательскому типу данных. Ящик преобразует между градусами Цельсия и Фаренгейта.
Вы можете найти завершенные файлы, созданные этим примером, в хранилище GitHub.
Предварительные условия
Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:
Создание пользовательского типа данных
Создайте пользовательский тип данных Temperatureи используйте его в качестве серийного свойства.
Создайте проект Unity с любым шаблоном.
Создайте папку с именем
bind-custom-data-typeдля хранения всех файлов.-
Создайте скрипт C# с именем
Temperature.csи замените его содержимое следующим:using System; namespace UIToolkitExamples { public enum TemperatureUnit { Celsius, Farenheit } [Serializable] public struct Temperature { public double value; public TemperatureUnit unit; } } -
Создайте скрипт C# с именем
PlanetScript.csи замените его содержимое следующим:using UnityEngine; namespace UIToolkitExamples { public class PlanetScript : MonoBehaviour { public Temperature coreTemperature; } }
Создание настраиваемого контроля
Создайте пользовательский редактор для Planet и пользовательский ящик свойств для Temperature.
В пользовательском ящике свойств реализуйте кнопку, которая преобразует температуру между Фаренгейтом и Целзиусом путем записи в свойства SerializedProperty (используйте doubleValue и enumValueIndex) и вызова SerializedObject.ApplyModifiedProperties().
Пользовательские свойства Draweris рассматривается как пользовательский контроль. Это встроенный контроль, который ведет себя в пользовательский способ.
Создайте папку под названием
Editor.-
В течение Редактор папка, создать C# скрипт назван
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")); } } } -
В течение Редактор папка, создать C# скрипт назван
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 со следующими элементами:
- А DoubleField
- Ан EnumField
- Кнопка
Установите binding-path двух полей на value и unit свойства Temperature.
В течение Редактор папка, создать папку с названием
Resources.-
В течение Ресурсы папка, создать UI Документ назван
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>
Проверка привязки
- Создайте пустой GameObject в сцене.
- В Hierarchy выберите GameObject.
- Перетащите PlanetScript.cs в Inspector. Это добавит компонент Planet Script в GameObject.
- Введите число в поле Температура и выберите единицу из раскрывающегося списка.
- Выберите кнопку Convert для преобразования между единицами. Если вы измените Inspector UI, свойство
Temperatureпользовательского контроля изменится.