データ バインディングは、MonoBehaviour
の string
プロパティなどの非 UI オブジェクトのプロパティを、TextField の value
プロパティなどの UI オブジェクトのプロパティと同期します。バインディングは、プロパティとそれを変更するビジュアルコントロールの間のリンクを指します。
データバインディングを使用して、プロパティと特定のビジュアル要素との間で値を同期させます。そのため、UI で値が変更されたときに、イベントハンドラー を書く必要はありません。
ノート: SerializedObject のデータバインディングはエディターでだけ機能し、ランタイムには機能しません。
シリアル化されたプロパティ にのみバインドする (関連付ける、紐づける) ことができます。つまり、ビジュアル要素をバインドできるのは、シリアル化システム と互換性のある以下のオブジェクトに限られます。
ScriptableObject
クラスMonoBehaviour
クラスint
、bool
、float
などの C# のプリミティブ型Vector3
、Color
、Object
などの Unity のネイティブの型INotifyValueChanged
インターフェースを実装したビジュアル要素の value
プロパティのみをバインドすることができます。例えば、TextField.value
を string
(文字列) にバインドすることはできますが、TextField.name
を string
にバインドすることはできません。
BindableElement
から派生するか、IBindable
インターフェースを実装するオブジェクトと任意のビジュアル要素の間でバインドすることができ ます。
バインディングを作成するには、Bind()
または BindProperty()
のいずれかを呼び出します。
Bind()
を呼び出すBind()
を呼び出して、要素をSerializedObject にバインドすることができます。要素をバインドする前に,バインドパスを設定し SerializedObject を作成する必要があります.
バインディングの SerializedProperty
に簡単にアクセスできない場合は、このメソッドを使用します。例として、C# スクリプトでバインディングを作成する を参照してください。
Bind()
拡張メソッドは、指定された bindingPath
プロパティを持つビジュアル要素の階層全体を設定します。Bind()
メソッドを、単一の要素またはバインドしたい階層の親に対して呼び出すことができます。例えば、Bind()
をエディターウィンドウの rootVisualElement
上で呼び出すことができます。これにより、指定した bindingPath
プロパティを持つすべての子要素がバインドされます。
Bind()
を Editor.CreateInspectorGUI()
または PropertyDrawer.CreatePropertyGUI()
のオーバーライドから呼び出さないようにしてください。これらのオーバーライドは、これらのメソッドが返すビジュアル要素で自動的に呼び出されます。
Unbind()
を呼び出すUnbind()
メソッドは、要素とその直接および間接のすべての子要素の値の追跡を停止します。一般に、ユーザーが Inspector やエディターウィンドウを閉じるときに追跡が停止するため、Unbind()
を呼び出す必要はありません。Unbind()
は、要素の生存期間に異なるターゲットに要素をバインドする必要がある場合に呼び出します。
C# でコンストラクターを呼び出して InspectorElement
を構築する場合、 コンストラクター呼び出し時にバインドが発生します。InspectorElement
を構築した後でバインドし直す場合は、Unbind()
を呼び出し、`Bind() を明示的に呼び出すか、親からのバインド操作でバインディングを作成する必要があります。
Bind()
を呼び出してバインディングを作成する場合、ビジュアル要素のバインディングパスをバインドしたいオブジェクトのプロパティ名に設定する必要があります。
例:
以下のようなコンポーネントスクリプトがある場合
using UnityEngine;
public class MyComp : MonoBehaviour
{
[SerializeField]
int m_Count;
}
ビジュアル要素を m_Count
にバインドするには、バインドパスを m_Count
に設定します。
ビジュアル要素を、ゲームオブジェクトの name プロパティ (m_Name
) にバインドする場合は、バインドパスを m_Name
に設定します。
バインディングパスは、UI Builder、UXML、または C# スクリプトで設定することができます。
binding-path
属性を設定します。例として、UXML でのバインディングパスの定義 を参照してください。IBindable
インターフェースから bindingPath
を設定します。例として バインディングパスによるバインド を参照してください。BindProperty()
を呼び出すBindProperty()
を呼び出して、要素を SerializedProperty
に直接バインドすることができます。
SerializedProperty
オブジェクトをすでに持っている場合、特に SerializedObject
のプロパティを走査して動的に UI を構築する場合に、このメソッドを使用します。例として バインディングパスなしのバインド を参照してください。
ビジュアル要素をソースオブジェクトのネストされたプロパティにバインドすることができます。これを行うには、要素のバインディングパスと最初の先祖のバインディングパスを組み合わせます。この方法は、以下の要素で使用します。
BindableElement
TemplateContainer
(UXML の <Instance>
タグに対応)GroupBox
例として、ネスト状のプロパティにバインド を参照してください。
バインドされたシリアル化されたプロパティが変更されたときにコールバックを受け取るバインディングを作成することができます。そのためには、TrackPropertyValue()
拡張メソッドを活用します。このメソッドは、任意の VisualElement
で利用可能です。これは、提供された SerializedProperty
が変更されたときに実行するコールバックを登録します。例として、シリアル化されたプロパティが変更されたときにコールバックを受け取る を参照してください。
また、バインドされたシリアライズオブジェクトのいずれかのプロパティが変更されたときにコールバックを受信するバインディングを作成することもできます。そのためには、TrackSerializedObjectValue()
拡張メソッドを活用します。これは、任意の VisualElement
で利用可能です。これは、提供された SerializedProperty
が変更されたときに実行するコールバックを登録します。例として、プロパティが変更されたときにコールバックを受け取る を参照してください。
カスタム要素を作成し、値のバインディング システムを通じて、シリアル化されたプロパティにバインドすることができます。
バインド可能なカスタム要素を作成するには、以下を行います。
BindableElement
から要素を継承するか、IBinding
インターフェースを実装します。INotifyValueChanged
インターフェースを実装します。SetValueWithoutNotify()
メソッドを INotifyValueChanged
インターフェースに実装します。value
プロパティアクセサーを INotifyValueChanged
インターフェースに実装します。例として、カスタムコントロールの作成とスタイル設定 を参照してください。
ノート: バインディングシステムでは、enum
の SerializedPropertyType でサポートされている型にしか要素をバインドできないため、カスタムデータ型をカスタム要素に直接バインドすることはできません。つまり、クラスや構造体、例えばMyStruct
という構造体を定義し、それをINotifyValueChanged<MyStruct>
を実装する要素にバインドすることはできません。しかし、カスタムデータ型のシリアル化可能なネストされたプロパティにバインドすることはできます。これには多相シリアル化が含まれます (フィールドが [SerializeReference]
属性 を使用する場合)。例として、カスタムコントロールをカスタムデータ型にバインドする を参照してください。
作成する UI の種類によって、バインドは様々なタイミングで発生します。これはバインド時間と呼ばれます。
以下の表では、操作の設定項目について説明します。
条件 | 自動バインド時間 (バインディングパスが設定されていることが前提) |
---|---|
C# で 構築される InspectorElement |
コンストラクター の呼び出し中 |
CreateInspectorGUI() または CreatePropertyGUI() メソッドが値を返すとき、その戻り値の下にある子要素 |
CreateInspectorGUI() または CreatePropertyGUI() が値を返した後。 |
Bind() または BindProperty() が親要素で呼び出されるとき、要素の下の子要素 |
Bind() または BindProperty() 呼び出しの間 |
Other | 自動バインディングはありません。要素またはその親の 1 つを手動でバインドする必要があります。 |
バインドタイムに関して、バインディングを作成する際のベストプラクティスを以下に示します。
Editor
またはカスタム PropertyDrawer
を作成する場合は、CreateInspectorGUI()
or CreatePropertyGUI()
のボディの終わりまでに ビジュアルツリー 内にあるすべてのビジュアル要素について、Bind()
または BindProperty()
を呼び出す代わりに、要素のバインディングパスを設定します。 これらの要素は CreateInspectorGUI()
または CreatePropertyGUI()
が返された後に自動的にバインドされます。ただし、それ以降にビジュアルツリーに要素を追加する場合は、Bind()
または BindProperty()
を呼び出して要素をバインドします。Bind()
または BindProperty()
を呼び出します。 Bind()
または BindProperty()
を呼び出して、複数のコントロールを同時にバインドする場合は、各コントロールのバインディングパスを設定してからすべてのコントロールを含む最下位の親要素で Bind()
を呼び出します。 Bind()
は、バインディングパスがある場合は呼び出される要素をバインドし、その子要素にバインディングパスがあれば子要素をすべて再帰的にバインドします。パフォーマンスへの悪影響を防ぐには、ビジュアル要素を Bind()
メソッドで複数回ビジュアル要素をバインドしないでください。データバインディングを使ったコード作成を学ぶには、以下の例を参照してください。