Version: Unity 6.0 (6000.0)
언어 : 한국어
IMGUI를 사용하여 커스텀 에디터 창 생성
IMGUI로 커스텀 에디터 생성

프로퍼티 드로어를 IMGUI와 함께 사용하여 인스펙터 커스터마이즈

참고: Unity 에디터를 확장하려면 IMGUI보다 더 현대적이고 유연하며 확장 가능한 솔루션을 제공하는 UI 툴킷을 사용할 것을 강력히 권장합니다.

프로퍼티 드로어는 스크립트에서 속성을 사용하거나 특정 Serializable 클래스가 표시되는 방식을 제어하여 인스펙터 창 에 특정 컨트롤이 표시되는 방식을 커스터마이즈할 때 사용할 수 있습니다.

프로퍼티 드로어는 다음 두 가지 용도로 사용됩니다.

  • 모든 Serializable 클래스 인스턴스의 GUI 커스터마이즈
  • 커스텀 프로퍼티 속성 을 사용하여 스크립트 멤버의 GUI 커스터마이즈

Serializable 클래스의 GUI 커스터마이즈

커스텀 Serializable 클래스가 있는 경우 프로퍼티 드로어 를 사용하여 인스펙터 에서 어떻게 표시되는지 제어할 수 있습니다. 아래 스크립트 예시의 Serializable 클래스 Ingredient를 고려하십시오. (참고: 이는 에디터 스크립트가 아닙니다. 프로퍼티 속성 클래스는 일반 스크립트 파일에 배치되어야 합니다.)

C#(예시):

using System;
using UnityEngine;

enum IngredientUnit { Spoon, Cup, Bowl, Piece }

// Custom serializable class
[Serializable]
public class Ingredient
{
    public string name;
    public int amount = 1;
    public IngredientUnit unit;
}

public class Recipe : MonoBehaviour
{
    public Ingredient potionResult;
    public Ingredient[] potionIngredients;
}

커스텀 프로퍼티 드로어를 사용하면 인스펙터에서 Ingredient 클래스의 모든 모습을 변경할 수 있습니다. 커스텀 프로퍼티 드로어가 있는 경우와 없는 경우 인스펙터의 Ingredient 프로퍼티의 모습을 비교해 보십시오.

커스텀 프로퍼티 드로어가 없는 경우(왼쪽)와 있는 경우(오른쪽)의 인스펙터 내 클래스
커스텀 프로퍼티 드로어가 없는 경우(왼쪽)와 있는 경우(오른쪽)의 인스펙터 내 클래스

CustomPropertyDrawer 속성을 이용하여 프로퍼티 드로어를 Serializable 클래스에 연결하고 드로어가 속한 Serializable 클래스의 유형을 전달할 수 있습니다.

C#(예시):

using UnityEditor;
using UnityEngine;

// IngredientDrawer
[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer
{
    // Draw the property inside the given rect
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

        // Draw label
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // Don't make child fields be indented
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // Calculate rects
        var amountRect = new Rect(position.x, position.y, 30, position.height);
        var unitRect = new Rect(position.x + 35, position.y, 50, position.height);
        var nameRect = new Rect(position.x + 90, position.y, position.width - 90, position.height);

        // Draw fields - pass GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none);
        EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);

        // Set indent back to what it was
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

프로퍼티 속성을 사용한 스크립트 멤버 GUI 커스터마이즈

프로퍼티 드로어 의 다른 용도는 커스텀 프로퍼티 속성 이 있는 스크립트에서 멤버의 모습을 변경하는 것입니다. 스크립트에서 플로트 또는 정수를 특정 범위로 제한하고 인스펙터 에 슬라이더로 표시하려고 한다고 가정해 보겠습니다. RangeAttribute 라는 빌트인 PropertyAttribute 를 사용하면 다음을 수행할 수 있습니다.

C#(예시):

// Show this float in the Inspector as a slider between 0 and 10
[Range(0f, 10f)]
float myFloat = 0f;

자체 PropertyAttribute 를 만들 수도 있습니다. RangeAttribute 에 대한 코드를 예로 들 수 있습니다. 속성은 PropertyAttribute 클래스를 확장해야 합니다. 원하는 경우 프로퍼티에서 파라미터를 사용하여 공용 멤버 변수로 저장할 수 있습니다.

C#(예시):

using UnityEngine;

public class MyRangeAttribute : PropertyAttribute 
{
        readonly float min;
        readonly float max;
        
        void MyRangeAttribute(float min, float max)
        {
            this.min = min;
            this.max = max;
        }
}

이제 속성이 있으므로 해당 속성이 있는 프로퍼티를 그리는 프로퍼티 드로어 를 만들어야 합니다. 드로어는 PropertyDrawer 클래스를 확장해야 하며, 드로어가 어떤 속성인지 알려 주는 CustomPropertyDrawer 속성이 있어야 합니다.

프로퍼티 드로어 클래스는 에디터 스트립트에서 에디터라는 폴더 안에 넣어야 합니다.

C#(예시):

using UnityEditor;
using UnityEngine;

// Tell the MyRangeDrawer that it is a drawer for properties with the MyRangeAttribute.
[CustomPropertyDrawer(typeof(MyRangeAttribute))]
public class RangeDrawer : PropertyDrawer
{
    // Draw the property inside the given rect
    void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // First get the attribute since it contains the range for the slider
        MyRangeAttribute range = (MyRangeAttribute)attribute;

        // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer.
        if (property.propertyType == SerializedPropertyType.Float)
            EditorGUI.Slider(position, property, range.min, range.max, label);
        else if (property.propertyType == SerializedPropertyType.Integer)
            EditorGUI.IntSlider(position, property, (int) range.min, (int) range.max, label);
        else
            EditorGUI.LabelField(position, label.text, "Use MyRange with float or int.");
    }
}

성능과 관련한 이유로 EditorGUILayout 함수를 프로퍼티 드로어와 함께 사용할 수 없습니다.

기본 오브젝트 레퍼런스

공개 오브젝트 필드 또는 SerializeField로 표시된 비공개 필드를 정의하는 경우 해당 필드에 대한 기본 레퍼런스를 설정할 수 있습니다. 프로젝트 창에서 스크립트 에셋을 선택하면 인스펙터 창에 기본 레퍼런스 필드가 표시됩니다.

참고: 각 PropertyDrawer를 이름이 일치하는 자체 파일로 유지하는 것이 좋습니다. 이렇게 하면 단일 PropertyDrawer에만 할당할 수 있으므로 기본 오브젝트 레퍼런스를 효율적으로 할당할 수 있습니다. 여러 유형이 동일한 파일에 있는 경우, 할당된 유형은 파일 이름과 일치하거나 파일에 정의된 첫 번째 유형입니다.

IMGUI를 사용하여 커스텀 에디터 창 생성
IMGUI로 커스텀 에디터 생성