Version: Unity 6.0 (6000.0)
言語 : 日本語
ランタイムバインディングのスタートガイド
ランタイムバインディングのデータソースの定義

C# スクリプトでのランタイムバインディングの作成

C# でビジュアル要素のプロパティをデータソースにバインドするには、DataBinding インスタンスを作成します。このバインディングの型では、バインディングインスタンスに dataSourcedataSourcePath を直接定義できます。

基本ワークフロー

C# でランタイムバインディングを作成するには、以下のステップに従います。

  1. バインディングの作成バインディングは、一意の ID を使用してビジュアル要素を作成、登録、または登録解除できるオブジェクトです。
  2. バインディングオブジェクトの データソースとデータソースパスを定義 します。データソースは、バインドするプロパティを含むオブジェクトです。データソースパスは、データソースからバインドするプロパティへの相対パスです。
  3. バインディングオブジェクトの バインディングモードと更新トリガーを定義 します。バインディングモードは、データソースと UI の間で変更を複製する方法を定義します。更新トリガーは、バインディングオブジェクトを更新するタイミングを定義します。
  4. ビジュアル要素にバインディングオブジェクトを登録します。
  5. 必要に応じて、型コンバータを追加して、データソースと UI の間でデータ型を変換 します。

以下は、バインディングオブジェクトを作成してビジュアル要素に登録する例です。

var dataSource = ScriptableObject.CreateInstance<ExampleObject>();

var root = new VisualElement
{
    name = "root",
    dataSource = dataSource
};

var vector3Field = new Vector3Field("Vec3 Field");

vector3Field.SetBinding("label", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.vector3Label)),
    bindingMode = BindingMode.ToTarget
});

vector3Field.SetBinding("value", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.vector3Value))
});

root.Add(vector3Field);

var floatField = new FloatField("Float Field") { value = 42.2f };

floatField.SetBinding("value", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.sumOfVector3Properties))
});

root.Add(floatField);

var label = new Label("Label")
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.dangerLevel))
};

// Here, we do not need to set the dataSourcePath because we will only use two bindings and they will use the same path,
// so we set the dataSourcePath on the Label directly instead.
var binding = new DataBinding
{
    bindingMode = BindingMode.ToTarget
};

// Add a custom float -> string converter
binding.sourceToUiConverters.AddConverter((ref float v) => 
{
    return v switch
    {
        >= 0 and < 1.0f/3.0f => "Danger",
        >= 1.0f/3.0f and < 2.0f/3.0f => "Neutral",
        _ => "Good"
    };
});

// Add a custom float -> StyleColor
binding.sourceToUiConverters.AddConverter((ref float v) => new StyleColor(Color.Lerp(Color.red, Color.green, v)));

// Since the binding is targeting the same data source property, we can re-use the same instance.
label.SetBinding("text", binding);
label.SetBinding("style.backgroundColor", binding);

root.Add(label);

以下の UXML に相当します。

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" 
editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:VisualElement data-source="ExampleObject.asset" name="VisualElement" >
        <ui:Vector3Field label="Vec3 Field">
            <Bindings>
                <ui:DataBinding property="label" data-source-path="vector3Label" binding-mode="ToSource" />
                <ui:DataBinding property="value" data-source-path="vector3Value" />
            </Bindings>
        </ui:Vector3Field>
        <ui:FloatField label="Float Field" value="42.2">
            <Bindings>
                <ui:DataBinding property="value" data-source-path="sumOfVector3Properties" binding-mode="ToTarget" />
            </Bindings>
        </ui:FloatField>
        <ui:Label text="Label" data-source-path="dangerLevel">
            <Bindings>
                <ui:DataBinding property="text" binding-mode="ToTarget" source-to-ui-converters="Value To Progress" />
                <ui:DataBinding property="style.backgroundColor" binding-mode="ToTarget" source-to-ui-converters="Value To Progress" />
            </Bindings>
    </ui:Label>
    </ui:VisualElement>
</ui:UXML>

バインディングオブジェクトの登録と登録解除

以下のメソッドを使用してバインディングオブジェクトを管理できます。

変更のレポート

バインド可能なプロパティは他のデータソースと同じ方法で作成できるため、VisualElement 型を データソース として使用できます。VisualElement 型とその他のデータソースの主な違いは、VisualElement 型にはビルトインのバージョン管理があるということです。変更を反映するには、VisualElement 型のビルトインバージョン管理を使用する必要があります。

変更をレポートするには、NotifyPropertyChanged メソッドを呼び出します。このメソッドは、変更されたプロパティを識別する BindingId を取得します。以下の例は、変更をレポートする方法を示しています。

// Creates a static readonly BindingId that is unique to this type. This is used to identify the property. 
public static readonly BindingId intValueProperty = nameof(intValue);

private int m_IntValue;

[CreateProperty]
public int intValue
{
    get => m_IntValue;
    set
    {
        if (m_IntValue == value)
            return;
        m_IntValue = value;
        
        // This instructs the binding system that a change occured.
        NotifyPropertyChanged(intValueProperty);
    }
}

推奨ガイド

パフォーマンスを最適化するには、以下のヒントとベストプラクティスに従ってください。

  • 正しいバインディング ID の使用: バインディングシステムはバインディング ID を使用して、バインディングオブジェクトと要素のターゲットプロパティを識別します。バインディング ID には要素のターゲットプロパティを使用してください。例えば、Vector3Fieldvalue プロパティにバインドする場合、バインディング ID は Vector3Field.valueProperty である必要があります。
  • バインディングで内部データを更新しない: バインドを使用してビジュアル要素の内部データを更新しないでください。例えば、バインドを使用して、Vector3Fieldxyz のサブ要素を同期しないでください。代わりに、バインディングを使用して、Vector3Fieldvalue プロパティとデータソースの Vector3 プロパティを同期します。

既知の制限

UI Toolkit は element.styleelement.resolvedStyle の変更をレポートしません。したがって、バインディングインスタンスを使用して要素の解決されたスタイルをターゲットにすることはできますが、要素への変更を追跡することはできません。

追加リソース

ランタイムバインディングのスタートガイド
ランタイムバインディングのデータソースの定義