绑定的目的是将对象内的属性同步到可见的 UI。 _绑定_是指属性和对属性进行修改的可视化控件之间的链接。
绑定是在对象和任何从 BindableElement 派生的或实现 IBindable 接口的 UIElement 之间完成。
从 UnityEditor.UIElements
命名空间中:
基类:
控件:
从 UnityEngine.UIElements
命名空间中:
基类
控件
进行绑定的方法是使用上面列出的命名空间之一中的控件,同时执行以下步骤。
以下代码片段显示了如何使用 C# 代码创建绑定。要使用此代码片段,请将本示例作为 C# 文件保存在项目的 Editor 文件夹中。将该 C# 文件命名为 SimpleBindingExample.cs
。
SimpleBindingExample.cs
的内容:
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace UIElementsExamples
{
public class SimpleBindingExample : EditorWindow
{
TextField m_ObjectNameBinding;
[MenuItem("Window/UIElementsExamples/Simple Binding Example")]
public static void ShowDefaultWindow()
{
var wnd = GetWindow<SimpleBindingExample>();
wnd.titleContent = new GUIContent("Simple Binding");
}
public void OnEnable()
{
var root = this.rootVisualElement;
m_ObjectNameBinding = new TextField("Object Name Binding");
m_ObjectNameBinding.bindingPath = "m_Name";
root.Add(m_ObjectNameBinding);
OnSelectionChange();
}
public void OnSelectionChange()
{
GameObject selectedObject = Selection.activeObject as GameObject;
if (selectedObject != null)
{
// 创建序列化对象
SerializedObject so = new SerializedObject(selectedObject);
// 将其绑定到层级视图的根目录。它将找到要绑定的正确对象...
rootVisualElement.Bind(so);
// ... 或者,也可以将其绑定到 TextField 本身。
// m_ObjectNameBinding.Bind(so);
}
else
{
// 取消对象与实际视觉元素的绑定
rootVisualElement.Unbind();
// m_ObjectNameBinding.Unbind();
// 删除绑定后,清除 TextField
m_ObjectNameBinding.value = "";
}
}
}
}
在 Unity 中,选择 Window > UIElementsExamples > Simple Binding Example。您可以使用此窗口在场景中选择任何游戏对象,并使用显示的 TextField 修改游戏对象的名称。
本节说明如何通过 UXML 层次视图设置来使用绑定。
在 UXML 中,属性 binding-path
在 TextField 控件中进行定义。就是这个属性会将控件绑定到对象的有效属性。
SimpleBindingExample.uxml
的内容:
<UXML xmlns:ui="UnityEngine.UIElements">
<ui:VisualElement name="top-element">
<ui:Label name="top-label" text="UXML-Defined Simple Binding"/>
<ui:TextField name="GameObjectName" label="Name" text="" binding-path="m_Name"/>
</ui:VisualElement>
</UXML>
SimpleBindingExample.cs
的内容:
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace UIElementsExamples
{
public class SimpleBindingExampleUXML : EditorWindow
{
[MenuItem("Window/UIElementsExamples/Simple Binding Example UXML")]
public static void ShowDefaultWindow()
{
var wnd = GetWindow<SimpleBindingExampleUXML>();
wnd.titleContent = new GUIContent("Simple Binding UXML");
}
public void OnEnable()
{
var root = this.rootVisualElement;
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/SimpleBindingExample.uxml");
visualTree.CloneTree(root);
OnSelectionChange();
}
public void OnSelectionChange()
{
GameObject selectedObject = Selection.activeObject as GameObject;
if (selectedObject != null)
{
// 创建序列化对象
SerializedObject so = new SerializedObject(selectedObject);
// 将其绑定到层级视图的根目录。它将找到要绑定的正确对象...
rootVisualElement.Bind(so);
}
else
{
// 取消对象与实际视觉元素的绑定
rootVisualElement.Unbind();
// 删除绑定后,清除 TextField
//(如果 Q() 返回 null,此代码不安全)
rootVisualElement.Q<TextField>("GameObjectName").value = "";
}
}
}
}
InspectorElement
是用于特定类型 Unity 对象的 Inspector 的 UIElement 对应元素。使用 InspectorElement
来检查对象具有以下优点:
在 Assets/Editor/SimpleBindingExample.cs
下可以找到另一个简单的绑定示例,提供了用法示例和过程概述。
Assets/Editor/SimpleBindingExample.cs
的内容:
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
namespace UIElementsExamples
{
public class SimpleBindingExampleUXML : EditorWindow
{
[MenuItem("Window/UIElementsExamples/Simple Binding Example UXML")]
public static void ShowDefaultWindow()
{
var wnd = GetWindow<SimpleBindingExampleUXML>();
wnd.titleContent = new GUIContent("Simple Binding UXML");
}
TankScript m_Tank;
public void OnEnable()
{
m_Tank = GameObject.FindObjectOfType<TankScript>();
if (m_Tank == null)
return;
var inspector = new InspectorElement(m_Tank);
rootVisualElement.Add(inspector);
}
}
}
此代码引用 TankScript
脚本并使用 InspectorElement
。
TankScript
脚本是分配给一个游戏对象的 MonoBehaviour 的示例。
Assets/TankScript.cs
的内容:
using UnityEngine;
[ExecuteInEditMode]
public class TankScript : MonoBehaviour
{
public string tankName = "Tank";
public float tankSize = 1;
private void Update()
{
gameObject.name = tankName;
gameObject.transform.localScale = new Vector3(tankSize, tankSize, tankSize);
}
}
InspectorElement 由特定 UI 进行自定义。这是通过 TankEditor
脚本完成的。TankEditor
脚本为 TankScript
类型定义了自定义编辑器。TankEditor
脚本还对层级视图使用 UXML 文件,并使用 USS 文件对 Inspector 进行样式设置。
Assets/Editor/TankEditor.cs
的内容:
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
[CustomEditor(typeof(TankScript))]
public class TankEditor : Editor
{
public override VisualElement CreateInspectorGUI()
{
var visualTree = Resources.Load("tank_inspector_uxml") as VisualTreeAsset;
var uxmlVE = visualTree.CloneTree();
uxmlVE.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Resources/tank_inspector_styles.uss"));
return uxmlVE;
}
}
Assets/Resources/tank_inspector_uxml.uxml
的内容:
<UXML xmlns:ui="UnityEngine.UIElements" xmlns:ue="UnityEditor.UIElements">
<ui:VisualElement name="row" class="container">
<ui:Label text="Tank Script - Custom Inspector" />
<ue:PropertyField binding-path="tankName" name="tank-name-field" />
<ue:PropertyField binding-path="tankSize" name="tank-size-field" />
</ui:VisualElement>
</UXML>
UXML 文件 tank_inspector_uxml.uxml
用于指定绑定。具体来说,对于每个 PropertyFields
标签,每个 binding-path
属性 (attribute) 都设置为要绑定的属性 (property)。UI 中显示的元素基于每个被绑定属性 (property) 的类型。
Assets/Resources/tank_inspector_styles.uss
的内容:
.container {
background-color: rgb(80, 80, 80);
flex-direction: column;
}
Label {
background-color: rgb(80, 80, 80);
}
TextField:hover {
background-color: rgb(255, 255, 0);
}
FloatField {
background-color: rgb(0, 0, 255);
}
USS 文件 tank_inspector_styles.uss
用于定义每个元素的样式。
下表列出了 PropertyField 支持的字段。每个字段都包含其数据类型。
字段 | Type |
---|---|
BoundsField | Bounds |
BoundsIntField | BoundsInt |
ColorField | Color |
CurveField | AnimationCurve |
FloatField | 浮点精度 |
GradientField | Gradient |
IntegerField | int |
IntegerField | int(对于 ArraySize) |
LayerMaskField | unit |
ObjectField | UnityEngine.Object |
PopupField<string> | Enum |
RectField | Rect |
RectIntField | RecInt |
TextField | string |
TextField,且 maxLength=1 | char |
Toggle | bool |
Vector2Field | Vector2 |
Vector2IntField | Vector2Int |
Vector3Field | Vector3 |
Vector3IntField | Vector3Int |
Vector4Field | Vector4 |