본문 바로가기
Works/Unity 3D

Custom Inspector GUI - PropertyDrawer

by Vader87 2015. 11. 20.
반응형

Inspector에 구분 선을 간단히 넣고 싶어 찾아보다가 PropertyAttribute를 사용한 방법을 찾게 되었다. 대부분의 경우 Editor를 상속받아 구현했었는데 이 방식은 필요 이상의 작업이 생기기 때문이다. PropertyAttribute와 PropertyDrawer에 대한 설명과 예제들이 많기 때문에 자세한 설명보다는 내 이해를 돕는데 필요한 설명들과 작업 중 생겼던 이슈와 해결 법 등을 위주로 적어본다.


Property

[명사] 재산, 소유물

Class의 멤버 변수에 접근하기 위한 속성 정의

예제 :

public class PropertyExample
{
     private int _number = 0;
     public int Number
     {
          get
          {
               return _number;
          }
          set
          {
               _number = value;
          }
     }
}


Attribute

[명사] 속성

메소드 및 변수에 추가적인 동작을 정의

예제 :

using UnityEngine;

public class AttributeExample : MonoBehaviour
{
     [SerializedField, Header("Header Attribute")]
     int _number = 0;
}


PropertyAttribute

말 그대로 속성 값의 특성을 설정한다. GUI 표기하는데 필요한 값이 더 있다면 이곳에 정의하면 간편하게 사용 가능하다.

예제 :

using System; using UnityEditor; // 사용 가능한 특성 정의 [AttributeUsage(AttributeTarget.Field)] public class CustomAttribute : PropertyAttribute { // 생성자 public CustomAttribute() { } }


PropertyDrawer

속성 값을 구현한 대로 그려준다.

예제 :

using UnityEditor;

// 어떤 PropertyAttribute를 사용해 구현하는지 정의
[CustomPropertyDrawer(typeof(CustomAttribute))]
public class CustomAttributeDrawer : PropertyDrawer
{
     public override bool CanCacheInspectorGUI(SerializedProperty property)
     {
          return base.CanCacheInspectorGUI(property);
     }

     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
     {
          return base.GetPropertyHeight(property, label);
     }

     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
     {
          base.OnGUI(position, property, label);
     }
}


CanCacheInspectorGUI

True 일 경우 GUI를 Cache 할 수 있다. 설명에 "Handles, GL, or some other method to draw directly into your rect" 일 경우에 False 해서 사용해라 라는 말이 있는데, 좀 더 조악하게 Unity Editor를 뜯어 고치고자 하면 사용되는 걸로 생각된다. 나는 편의를 위해 찾은 거니 패스.


GetPropertyHeight

Property가 Inspector에서 사용할 영역의 높이 값을 반환한다. 이 값은 OnGUI에서 넘겨주는 Rect의 height 값에 영향을 준다. 이 값을 수정했으면 GUI를 구성할 때 OnGUI에서 넘겨주는 Rect의 height 값을 사용하지 말고, EditorGUI.GetPropertyHeight를 사용하면 원래 Inspector에서 Property들이 갖는 높이 값을 얻을 수 있다.


OnGUI

Property가 Inspector에서 어떻게 표현될지 구현한다. EditorGUI를 메인으로 사용해 구현한다. 반드시 인지는 모르겠으나 대부분의 예제에서 구현을 EditorGUI를 사용해 구현했다. 다른 GUI 방식에도 정상 작동하는지는 테스트가 필요하다.


PropertyAttribute 사용법

Attribute를 사용할 때와 동일하다.

예제 :

using UnityEngine;

public class CustomAttributeDemo : MonoBehaviour
{
     [SerializeField, CustomAttribute]
     string _text = string.Empty;
}


결과 :



"No GUI Implemented"라는 글이 겹쳐서 출력 되는 것을 확인할 수 있는데 이는 OnGUI 부분을 구현하지 않고 base.OnGUI를 사용해 생기는 현상이다. OnGUI 부분을 수정해 작업하면 사라진다.


작업 중 이슈 내역 작성 중....


원래 구현하고자 하는 것은 구분 선이었으나 이 방법으로는 구현이 어렵다고 결론 짓게 되었다.

배열에 사용 시 변수 타입 값에 종속이 되는지 생각했던 것과는 다르게 배열의 각 변수의 Property에 반영이 되는 결과가 나왔기 때문이다.

Unity의 Header Attribute가 있으니 간단한 구현 방법이 있을 것이라 예상하고 시작한 작업이었으나 예상은 실패.

PropertyAttribute와 PropertyDrawer를 공부한 걸로 만족하고 마무리...


참조

Microsoft Docs/.NET/C# 가이드/프로그래밍 가이드/클래스 및 구조체

Microsoft Docs/.NET/.NET API 브라우저/Sytem/Attribute

Unity 자습서>Scripting>Properties

Unity 자습서>Scripting> Attribute

Unity 문서>스크립팅 API/PropertyAttribute

Unity 문서>스크립팅 API/PropertyDrawer

Unity 문서>매뉴얼>에디터 확장>프로퍼티 드로어

PropertyDrawer "No GUI implemented" error in Editor

[에디터 확장 입문] 번역 10장 PropertyDrawer


반응형

댓글