Version: 2019.2
빌트인 컨트롤
IMGUI 지원

바인딩

바인딩의 목적은 오브젝트 내 프로퍼티를 표시되는 UI와 동기화하는 것입니다. 바인딩 은 프로퍼티와 해당 프로퍼티를 수정하는 시각 컨트롤 간의 연결을 의미합니다.

바인딩은 오브젝트, 그리고 BindableElement에서 파생되거나 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
  • TextField
  • Toggle

바인딩은 위에 나열된 네임스페이스 중 하나의 컨트롤을 사용하는 동안 다음 단계에 따라 이루어집니다.

  1. UI가 바인딩할 프로퍼티를 알 수 있도록 컨트롤에서 IBindable 인터페이스의 bindingPath를 지정합니다. C# 또는 UXML을 통해서도 가능합니다. 각 예제는 이 항목 후반에 제공됩니다.
  2. 바인딩할 오브젝트에 대한 SerializedObject를 만듭니다.
  3. 이 오브젝트를 UIElements 컨트롤 또는 해당 부모 중 하나에 바인딩합니다.

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 = "";
           }
       }
   }
}

Unity에서 Window > UIElementsExamples > Simple Binding Example 을 선택합니다. 이 창을 사용하여 씬 내 게임 오브젝트를 선택하고 표시된 TextField에서 이름을 수정할 수 있습니다.

UXML을 사용한 바인딩

이 섹션에서는 UXML 계층 구조 설정을 통해 바인딩을 사용하는 방법을 보여줍니다.

UXML에서 binding-path 속성은 TextField 컨트롤에서 정의됩니다. 이를 통해 컨트롤이 오브젝트의 유효한 프로퍼티에 바인딩됩니다.

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>

tank_inspector_uxml.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);
}

tank_inspector_styles.uss USS 파일은 각 요소의 스타일을 지정합니다.

다음 표에는 PropertyField에서 지원되는 필드가 나와 있습니다. 각 필드에는 해당 데이터 타입이 들어 있습니다.

필드 Type
BoundsField Bounds
BoundsIntField BoundsInt
ColorField 색상
CurveField AnimationCurve
FloatField float
GradientField 그레디언트
IntegerField int
IntegerField int, for the ArraySize
LayerMaskField unit
ObjectField UnityEngine.Object
PopupField<string> 열거형
RectField Rect
RectIntField RecInt
TextField 문자열
TextField, with a maxLength=1 char
Toggle bool
Vector2Field Vector2
Vector2IntField Vector2Int
Vector3Field Vector3
Vector3IntField Vector3Int
Vector4Field Vector4
빌트인 컨트롤
IMGUI 지원