유니티 커스텀 에디터(1)

Proffeine0327·2023년 5월 3일
0

Unity Custom Editor

목록 보기
2/2

먼저 컴포넌트의 Inspector창을 수정하는 것부터 알아보자.
Inspector창을 수정하는 데에는 제약이 있다.

  1. SerializeField, public이 붙은 변수만을 수정할 수 있다.
  2. 유니티가 지원하지 않는 변수는 수정할 수 없다. (Dictionary같은 변수들은 Inspector창에 표시가 안되는데, 이런놈들은 수정할 수 없다.)
  3. MonoBehaviour, ScriptableObject만 수정할 수 있다. (Custom Class는 수정 방법이 따로 있다.)
  4. 전처리 지시문 #if UNITY_EDITOR을 사용해서 전체 스크립트를 감싸야지 정상적인 빌드가 된다.

자세한건 후술하겠다.


먼저 MonoBehaviour 클래스 하나를 생성해보자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Human : MonoBehaviour
{
    public string name;
    public int age;
    public float height;
}


우리는 이 스크립트의 에디터 클래스를 만들어서 공부를 할것이다.
HumanEditor로 Script를 하나 더 만들고 다음과 같이 코드를 쓰자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR 								// 1)
using UnityEditor;

[CustomEditor(typeof(Human))] 					// 2) 
public class HumanEditor : Editor 				// 3)
{
    public override void OnInspectorGUI()		// 4)
    {
        base.OnInspectorGUI();
    }
}
#endif

1) 전처리 지시문이다. 에디터 관련 코드가 들어있으면 빌드할때 오류를 내기 때문에, 전처리 지시문에서 UNITY_EDITOR 조건을 통해 유니티 에디터에서만 컴파일 되게 해야한다.

2) UnityEditor에 포함되어있는 Attribute이다. Inspector창을 커스텀할 클래스를 typeof를 이용하여 전달하면 된다.

3) Editor클래스를 상속하는 HumanEditor 클래스이다. 밑의 override 함수 OnInspectorGUI함수를 사용하기 위해서 필수적이다.

4) OnInspectorGUI함수다, base는 Inspector에서 기본적으로 보여주는 화면.


이제 변수를 가져오는 법을 알아보자. 당연하게도 Inspector을 수정한다는 소리는, 스크립트의 Instance가 있다는 말이다.

스크립트의 Instance는 serializedObject 변수로 가져올 수 있다.
또한 변수를 가져오기 위해서는 FindProperty함수와 변수의 이름을 이용해서 가져와야 한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;  

[CustomEditor(typeof(Human))]
public class HumanEditor : Editor
{
    public override void OnInspectorGUI()
    {
        var name = serializedObject.FindProperty("name"); 
        var age = serializedObject.FindProperty("age");
        var height = serializedObject.FindProperty("height");
    }
}
#endif

이렇게 가져온 변수들은 SerializedProperty클래스이며, 내부 속성들을 이용해 변수의 값을 가져올 수 있다.

예를들어 human에서의 name의 값은 string이므로 name.stringValue를 통하여 수정을 해야한다. 맞지 않는 타입의 값을 수정하면 오류를 출력한다.


이제 가져온 이름들을 표시해보자. Inspector에 여러가지 입력 필드를 표시하는 속성은 EditorGUILayout, GUILayout에 들어있다. 에디터 필드들에 대한 정리는 고라니 유튜브에 정리가 잘 되어있으니 참고 바란다.

우리는 변수들의 이름을 한번 한국어로 표시되게 해보자

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;

[CustomEditor(typeof(Human))]
public class HumanEditor : Editor
{
    public override void OnInspectorGUI()
    {
        var name = serializedObject.FindProperty("name");
        var age = serializedObject.FindProperty("age");
        var height = serializedObject.FindProperty("height");

		// 문자열 필드를 표시
        name.stringValue = EditorGUILayout.TextField("이름", name.stringValue);
        // 정수 필드를 표시
        age.intValue = EditorGUILayout.IntField("나이", age.intValue);
        // 실수 필드를 표시
        height.floatValue = EditorGUILayout.FloatField("키", height.floatValue);
    }
}
#endif

아마도 이상태로 값을 조정할려하면 값이 변하지 않을것이다.
Inspetor에서 변한 값은 바로 적용되고, 저장되는것이 아닌, 변경점을 저장하는 함수인 serializedObject.ApplyModifiedProperties를 호출해야한다. (Dirty Flag)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;

[CustomEditor(typeof(Human))]
public class HumanEditor : Editor
{
    public override void OnInspectorGUI()
    {
        var name = serializedObject.FindProperty("name");
        var age = serializedObject.FindProperty("age");
        var height = serializedObject.FindProperty("height");

        name.stringValue = EditorGUILayout.TextField("이름", name.stringValue);
        age.intValue = EditorGUILayout.IntField("나이", age.intValue);
        height.floatValue = EditorGUILayout.FloatField("키", height.floatValue);

        serializedObject.ApplyModifiedProperties();
    }
}
#endif
profile
Programmer needs Caffeine / 공부하는 학생

0개의 댓글