Data bindings synchronize properties of non-UI object, such as a string
property on a MonoBehaviour
, with properties of UI 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 element, 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.
例如:
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 GameObject’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.
Note: You can’t bind custom data types directly to custom elements because the binding system only allows you to bind an element to a type supported by SerializedPropertyType of enum
. This means you can’t define a class or structure, for example a struct called MyStruct
, and bind it to an element that implements INotifyValueChanged<MyStruct>
. However, you can bind to serializable nested properties of custom data types. This includes polymorphic serialization (when a field uses the [SerializeReference]
attribute). See Bind a custom control to custom data type for an example.
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 tree by the end of the body of 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:
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.