Unity 6.3
0 онлайн 36 гостей 3 в системе
Вход

Привязка настраиваемого контроля

Версия: 2021.3+

В этом примере показано, как связать пользовательский контроллер с основным типом Unity.

Примерный обзор

В примере создается пользовательский контроллер, который отображает изображение 2D. Он использует пользовательский контроллер в пользовательском редакторе для нового типа ассета и связывает пользовательский контроллер с полем в ассете нового типа.

Пользовательское управление для изображения 2D, отображаемого в Unity Editor.
Пользовательское управление для изображения 2D, отображаемого в Unity Editor.

Вы можете найти завершенные файлы, созданные этим примером, в хранилище GitHub.

Предварительные условия

Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:

Создание серийного объекта

Создайте серийный объект, содержащий Texture2D.

  1. Создайте проект Unity с любым шаблоном.
  2. В окне Project создайте папку с именем bind-custom-control для хранения файлов.
  3. Создайте скрипт C# с именем TextureAsset.cs и замените его содержимое следующим:
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. В течение Редактор папка, создать C# скрипт назван TexturePreviewElement.cs.
  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. В течение Редактор папка, создать папку с названием Resources.
  2. В течение Ресурсы папка, создать StyleSheet названный texture_preview_element.uss и заменить его содержание следующим:
.texture-preview-element {
    width: 200px;
    height: 200px;
}

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

Создать Inspector UI

Создайте объект Inspector UI и привязайте пользовательский контроллер к объекту Texture2D.

  1. В течение Редактор папка, создать C# скрипт назван TextureAssetEditor.cs и заменить его содержание следующим:
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

Создайте файл UXML с TexturePreviewElement и установите свойство binding-path на texture. Это привязывает TexturePreviewElement к TextureAsset.texture.

  1. В течение Редактор папка, создать UI Документ назван texture_asset_editor.uxml и заменить его содержание следующим:
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:example="UIToolkitExamples" editor-extension-mode="True">
    <example:TexturePreviewElement binding-path="texture" />
</ui:UXML>
  1. В окне Project выберите TextureAssetEditor.cs.
  2. Перетащите texture_asset_editor.uxml в Визуальное Дерево в Inspector.

Проверка привязки

  1. В меню выберите Ассеты > Создать > UIToolkitExamples > TextureAsset. Это создаст экземпляр TextureAsset.
  2. Выберите новый объект TextureAsset. В Inspectorвы можете увидеть Элемент Предварительного Просмотра Текстуры. Если вы помещаете ссылку на ресурс текстуры в поле, вы можете увидеть предварительный просмотр над полем. Если вы измените ссылку на ресурс в Элементе Предварительного Просмотра Текстуры в UI, то TextureAsset.texture изменится.

Дополнительные ресурсы