Version: 2020.3
Controls reference
IMGUI Support

バインディング

バインディングの目的は、オブジェクト内のプロパティを表示可能な UI に同期することです。バインディングとは、プロパティとそれを変更するビジュアルコントロールの間のリンク (紐づけ) を指します。

バインディングは、オブジェクトと、BindableElement から派生した UIElement、または IBindable インターフェースを実装した UIElement の間で行われます。

UnityEditor.UIElements 名前空間から

基本クラス

  • BaseCompositeField
  • BasePopupField
  • CompoundFields
  • TextValueField

コントロール

  • InspectorElement
  • ProgressBar
  • BoundsField
  • BoundsIntField
  • ColorField
  • CurveField
  • DoubleField
  • EnumField
  • FloatField
  • GradientField
  • IntegerField
  • LayerField
  • LayerMaskField
  • LongField
  • MaskField
  • ObjectField
  • PopupField
  • PropertyControl
  • RectField
  • RectIntField
  • TagField
  • Vector2Field
  • Vector2IntField
  • Vector3Field
  • Vector3IntField
  • Vector4Field

UnityEngine.UIElements 名前空間から:

基本クラス

  • BaseField
  • BaseSlider
  • TextInputBaseField
  • TemplateContainer

コントロール

  • Foldout
  • MinMaxSlider
  • Slider
  • SliderInt
  • テキストフィールド
  • トグルボタン

バインドは、上記の名前空間の 1 つからコントロールを使用する際に、以下の手順で行います。

  1. コントロールで、IBindable インターフェースの bindingPath を指定して、どのプロパティをバインドするかが UI にわかるようにします。これは C# または UXML で行うことができます。それぞれの例は、後に紹介します。
  2. バインドされるオブジェクトの SerializedObject を作成します。
  3. Bind this object to the Control or one of its parents.

C# とのバインディング

以下のコードスニペットは C# コードとのバインディングの方法を示しています。このスニペットを使用するには、プロジェクトのエディターフォルダーに C# ファイルとしてこのサンプルを保存します。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)
           {
               // Create serialization object
               SerializedObject so = new SerializedObject(selectedObject);
               // Bind it to the root of the hierarchy. It will find the right object to bind to...
               rootVisualElement.Bind(so);

               // ... or alternatively you can also bind it to the TextField itself.
               // m_ObjectNameBinding.Bind(so);
           }
           else
           {
               // Unbind the object from the actual visual element
               rootVisualElement.Unbind();

               // m_ObjectNameBinding.Unbind();

               // Clear the TextField after the binding is removed
               m_ObjectNameBinding.value = "";
           }
       }
   }
}

In Unity, select Window > UIElementsExamples > Simple Binding Example. You can use this window to select any GameObject in your scene and modify its name with the TextField shown.

UXML とのバインディング

このセクションでは、UXML 階層の設定を通してバインディングの使用法を説明します。

UXML では、属性 binding-path は TextField コントロールで定義されます。binding-pathが、コントロールをオブジェクトの実効プロパティにバインドします。

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)
           {
               // Create serialization object
               SerializedObject so = new SerializedObject(selectedObject);
               // Bind it to the root of the hierarchy. It will find the right object to bind to...
               rootVisualElement.Bind(so);
           }
           else
           {
               // Unbind the object from the actual visual element
               rootVisualElement.Unbind();

               // Clear the TextField after the binding is removed
               // (this code is not safe if the Q() returns null)
               rootVisualElement.Q<TextField>("GameObjectName").value = "";
           }
       }
   }
}

InspectorElement 内でバインディングを使用

InspectorElement はインスペクターの UIElement です。つまり、特定のタイプの Unity オブジェクトです。InspectorElement を使用してオブジェクトを確認すると、以下の利点があります。

  • UI を作成します。
  • オブジェクトと UI を自動的にバインドします。

別の簡単なバインディングの例は 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 ファイルを使用してインスペクターのスタイルを設定します。

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 属性が、バインドするプロパティに設定されます。UI に表示される要素は、バインドされた各プロパティのタイプに基づいています。

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 でサポートされているフィールドの一覧です。各フィールドにはデータ型が含まれます。

フィールド
BoundsField Bounds
BoundsIntField BoundsInt
ColorField Color
CurveField AnimationCurve
FloatField float
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
Controls reference
IMGUI Support