Data bindings synchronize properties of non-UI object, such as a string
property on a MonoBehaviour
, with properties of UI(User Interface) Allows a user to interact with your application. Unity currently supports three UI systems. More info
See in Glossary objects, such as the value
property of a TextField. A binding refers to the link between the property and the visual control that modifies it.
Use data binding to synchronize values between a property and a specific visual elementA node of a visual tree that instantiates or derives from the C# VisualElement
class. You can style the look, define the behaviour, and display it on screen as part of the UI. More info
See in Glossary, so you don’t need to write event handlers when the value changes in the UI.
Note: SerializedObject data binding only works in the Editor, not at runtime.
You can only bind to serialized properties. This means you can only bind visual elements to the following objects that are compatible with the Serialization system:
ScriptableObject
classesMonoBehaviour
classesint
, bool
, float
, and so on.Vector3
, Color
, Object
, and so on.You can only bind the value
property of visual elements that implement the INotifyValueChanged
interface. For example, you can bind TextField.value
to a string
, but you can’t bind TextField.name
to a string
.
You can bind between an object and any visual element that either derives from BindableElement
or implements the IBindable
interface.
To create a binding, either call Bind()
or BindProperty()
.
Bind()
You can call Bind()
to bind an element to a SerializedObject. Before you bind an element, you must set the binding path and create a SerializedObject.
Use this method if you don’t have easy access to the SerializedProperty
for the binding. See Create a binding with a C# script for an example.
The Bind()
extension method sets up an entire hierarchy of visual elements with specified bindingPath
properties. You can call the Bind()
method on a single element or the parent of the hierarchy that you want to bind. For example, you can call Bind()
on the rootVisualElement
of an Editor window. This binds all child elements with specified bindingPath
properties.
Don’t call Bind()
from the Editor.CreateInspectorGUI()
or PropertyDrawer.CreatePropertyGUI()
override. These overrides are called automatically on the visual elements that these methods return.
Unbind()
The Unbind()
method stops the value tracking for the element and all its direct and indirect child elements. In general, you don’t need to call Unbind()
because tracking stops when a user closes the Inspector or Editor window. Call Unbind()
if you must bind elements to different targets in their lifetimes.
If you construct an InspectorElement
in C# by calling its constructor, binding occurs during the constructor call. If you want to rebind an InspectorElement
after it has been constructed, you must call Unbind()
and then either call Bind()
explicitly or let a bind operation from a parent create a binding.
If you call Bind()
to create the binding, you must set the visual element’s binding path to the property name of the object that you want to bind to.
For example:
If you have the following component script:
using UnityEngine;
public class MyComp : MonoBehaviour
{
[SerializeField]
int m_Count;
}
To bind your visual element to m_Count
, set the binding path to m_Count
.
If you want to bind a visual element to a GameObjectThe fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary’s name property, which is m_Name
, set the binding path to m_Name
.
You can set the binding path in UI Builder, UXML, or with a C# script:
binding-path
attribute for a visual element. See Define the binding path in UXML for an example.bindingPath
from the IBindable
interface. See Bind with the binding path for an example.BindProperty()
You can call BindProperty()
to bind an element to a SerializedProperty
directly.
Use this method if you already have a SerializedProperty
object, and especially if you traverse the properties of a SerializedObject
to build a UI dynamically. See Bind without the binding path for an example.
You can bind a visual element to nested properties in the source object. To do so, combine the binding path of an element with the binding path of the first ancestor. Use this method with the following elements:
BindableElement
TemplateContainer
(corresponds to the <Instance>
tag in UXML)GroupBox
See Bind to nested properties for an example.
You can create a binding to receive a callback when a bound serialized property changes. To do so, leverage the TrackPropertyValue()
extension method, which is available to any VisualElement
. This registers a callback that executes when the provided SerializedProperty
changes. See Receive callbacks when a serialized property changes for an example.
You can also create a binding to receive a callback when any properties of the bound serialized object changes. To do so, leverage the TrackSerializedObjectValue()
extension method, which is available to any VisualElement
. This registers a callback that executes when the provided SerializedProperty
changes. See Receive callbacks when any properties change for an example.
You can create custom elements and bind them to serialized properties through the value binding system.
To create bindable custom elements:
BindableElement
or implement the IBinding
interface.INotifyValueChanged
interface.SetValueWithoutNotify()
method to the INotifyValueChanged
interface.value
property accessors to the INotifyValueChanged
interface.See Create and style a custom control for an example.
When writing a custom inspectors you don’t have to explicitely bind a serialized object to the visual tree like in the editor windows examples above. This step is done implicitely after the CreateInspectorGUI
method finishes. This automatic binding step is only performed at that time. If you add a field outside of a callback to the CreateInspectorGUI
method, you will need to bind it manually. Otherwise it might fail to render or produce undefined visual results.
Based on the type of UI you create, binding occurs at various times. This is called bind time.
The following table describes the bind time of a control:
Condition | Automatic bind time (assuming binding path was set) |
---|---|
An InspectorElement constructed in C# |
During the constructor call |
A child element that is under the return value of CreateInspectorGUI() or CreatePropertyGUI() when those methods return |
After CreateInspectorGUI() or CreatePropertyGUI() returns |
A child element that is under an element when Bind() or BindProperty() is called on the parent element |
During the Bind() or BindProperty() call |
Other | No automatic binding; you must bind the element or one of its parents manually |
The following are best practices when creating a binding regarding bind time:
Editor
or custom PropertyDrawer
, set the elements’ binding paths instead of calling Bind()
or BindProperty()
on any visual elements that are in the visual treeAn object graph, made of lightweight nodes, that holds all the elements in a window or panel. It defines every UI you build with the UI Toolkit.CreateInspectorGUI()
or CreatePropertyGUI()
. These elements are bound automatically after CreateInspectorGUI()
or CreatePropertyGUI()
returns. However, if you add any elements to the visual tree after that point, call Bind()
or BindProperty()
to bind them.Bind()
or BindProperty()
regardless of the time at which the elements get added to the visual tree. If you call Bind()
or BindProperty()
and bind multiple controls at the same time, set the binding path of each control and then call Bind()
on the lowest-level parent element that encompasses all the controls. Bind()
binds the element on which it’s called if it has a binding path and recursively binds all its child elements if they have binding paths. To prevent a negative performance impact, don’t bind a visual element with the Bind()
method more than once.Try the following examples to learn how to code with data binding: