版本: 2021.3+
此示例演示如何将自定义控件绑定到原生 Unity 类型。
该示例创建了一个自定义控件,用于显示 2D 图像。它在自定义编辑器中使用自定义控件,用于新的资产类型,并将自定义控件绑定到新类型资产中的字段。
您可以在此 GitHub 存储库 中找到此示例创建的完整文件。
本指南适用于熟悉 Unity 编辑器、UI(用户界面) 允许用户与您的应用程序进行交互。Unity 目前支持三种 UI 系统。 更多信息
请参阅 术语表 工具包和 C# 脚本的开发人员。在开始之前,请先熟悉以下内容
BindableElement
INotifyValueChanged
创建包含 Texture2D 的序列化对象。
Assets
文件夹内容的窗口(项目选项卡) 更多信息bind-custom-control
的文件夹来存储文件。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 为其设置样式。
Editor
的文件夹。TexturePreviewElement.cs
的 C# 脚本。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);
}
}
}
}
}
Resources
的文件夹。texture_preview_element.uss
的样式表,并将它的内容替换为以下内容.texture-preview-element {
width: 200px;
height: 200px;
}
.texture-preview-element > .unity-image {
flex-grow: 1;
}
创建 检查器一个 Unity 窗口,显示当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。 更多信息
请参阅 术语表 UI,并将自定义控件绑定到 Texture2D 对象。
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();
}
}
}
创建一个包含 TexturePreviewElement 的 UXML 文件,并将 binding-path
属性设置为 texture
。这将 TexturePreviewElement 绑定到 TextureAsset.texture
。
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>
TextureAsset
的实例。TextureAsset.texture
将发生改变。