본문 바로가기

유니티

유니티 - CustomEditor 사용법

유니티에서 커스텀 에디터를 작성하면 개발자들이 더 직관적으로 에디터를 사용할 수 있도록 도와줄 수 있습니다. 커스텀 에디터를 사용하여 Unity Inspector를 확장하거나, 새로 만들거나, 사용자 정의 도구를 추가할 수 있습니다. 

또한 커스텀 에디터는 개발자 뿐만 아니라 기획자나 아트분들까지 협업할 때 더 편하게 작업이 가능하게 만들어 줍니다.

 

커스텀 에디터는 보통 데이터를 조작할 때 사용하게 된다. 

 

예로 글쓴이의 오브젝트 풀 사이즈 데이터의 코드를 봐보자!

 

우선 데이터가 있어야 합니다.

Pool Size를 관리할 데이터

이 클래스 코드는 오브젝트 풀링에서 메모리를 조금 더 효율적으로 관리하기 위해서 특정 오브젝트의 타입은 사이즈를 정해두려고 만든 데이터 코드이다.

 

이 스크립터블 오브젝트로 되어있는 데이터 클래스를 어떻게 커스텀하게 만들 것인가?

 

1. Assets 경로의 Editor 폴더 안 클래스를 생성해야한다.

 

2. Editor를 상속받고, 어트리뷰트에 PoolSizeData Class를 등록해놔야한다. 

 

3. 커스텀 에디터 클래스에서 인스펙터 창에 그려줄 UI를 직접 그릴 수 있게 해주는 함수를 작성한다.

 

여기서 원래 내가 보여주고 있던 형태를 보여주려면 base.OnInspectorGUI()를 사용하면 된다.

새롭게 바꿀거라면 사용하지 않으면 된다.

 

여기서 해당 데이터를 수정하는 방법에는 2가지가 있다.

1. 실제 데이터 인스턴스를 직접 참조해서 변경하는 방법

2. Unity 내부 데이터 구조를 간접적으로 조작

 

1.직접 참조를 해서 가져오는 방법

// 현재 에디터가 대상하고 있는 PoolSizeData 객체 가져오기
PoolSizeData data = (PoolSizeData)target;

 

2. 내부 데이터 구조를 간접적으로 조작하는 방법

private SerializedProperty poolSettingsProperty;

private void OnEnable()
{
    // poolSettings 리스트를 SerializedProperty로 가져옴
    poolSettingsProperty = serializedObject.FindProperty("poolSettings");
}

이 코드는 Unity의 직렬화된 메모리 구조에서 poolSettings라는 필드를 찾아서, 그에 대한 안전한 참조(SerializedProperty)를 가져오는 것

 

구분                                                         직접 접근                                                           SerializedProperty 사용

속도 빠름 느림 (리플렉션 기반)
Undo ❌ 수동으로 처리해야 함 ✅ 자동 지원
Prefab/다중 오브젝트 편집 ❌ 지원 안 됨 ✅ 지원
Inspector 반영 ❌ 수동으로 SetDirty 필요 ✅ 자동 처리
안전성 Unity 내부 시스템과 충돌 가능 Unity 시스템과 연동됨

 

이러한 비교가 될 수 있겠다.

그래서 정말 테스트 용도로 빠르게 만들려고 하면 직접 접근도 나쁘진 않지만 Undo 기능이 생각보다 되게 도움이 많이 된다. 그래서 SerializedProperty를 사용하는게 더 좋다고 생각한다.

 

GUI 에는 리스트에 풀 오브젝트 타입과 해당 타입의 사이즈를 추가하는 코드를 작성해보겠다.

 

먼저 2개의 방법으로 같은 GUI를 보여줘보겠다.  

 

1. 직접 접근

 

2. SerializedProperty 사용

 

결과물

같은 타입이 들어오면 경고 문구가 나오고, 타입을 정하고, 사이즈를 정할 수 있다.

그리고 버튼들의 색상을 지정해주면서 조금 더 시각적으로 잘보이게 내놨다.

 

 

여기서 에디터가 그리는 값과 동기화하는 함수와 변경을 했으면 반영이 되는 함수는 꼭 작성해줘야 한다.

serializedObject.Update(); // 에디터가 그리는 값과 실제 오브젝트 값 사이를 동기화해주는 함수
serializedObject.ApplyModifiedProperties(); // 변경사항 반영

 

EditorGUILayout 11가지 종류 

 

1. EditorGUILayout.LabelField("텍스트", EditorStyles.boldLabel);

 

  • 역할: 읽기 전용 텍스트 출력.
  • 사용 예: 제목, 설명 등 표시용.

2. EditorGUILayout.HelpBox("설명 메시지", MessageType.Info);

 

  • 역할: 설명 또는 경고/오류 박스 표시.
  • MessageType은 Info, Warning, Error 가능.
  • 사용 예: 사용자에게 가이드 메시지 제공.

3. EditorGUILayout.PropertyField(serializedProperty, new GUIContent("이름"));

 

  • 역할: SerializedProperty를 자동으로 UI로 렌더링.
  • 사용 예: OnEnable에서 FindProperty로 가져온 필드들을 UI에 표시할 때.

4. myEnum = (MyEnumType)EditorGUILayout.EnumPopup("이름", myEnum);

 

  • 역할: 열거형 드롭다운 메뉴.
  • 사용 예: Enum 값 직접 수정할 때.

5. intVal = EditorGUILayout.IntField("Max Count", intVal);
- floatVal = EditorGUILayout.FloatField("Speed", floatVal);
- stringVal = EditorGUILayout.TextField("Name", stringVal);
- boolVal = EditorGUILayout.Toggle("Is Active", boolVal);

 

  • 역할: 기본 타입들을 직접 수정할 수 있는 필드.
  • IntField, FloatField, TextField, Toggle 등 다양한 버전 존재.
  • 사용 예: 값 하나하나를 수동으로 관리할 때.

6. EditorGUILayout.BeginVertical("box");
... // 내부 내용
- EditorGUILayout.EndVertical();

 

  • 역할: UI를 세로 정렬하며 그룹화. "box"는 테두리 스타일.
  • 사용 예: 여러 관련 필드를 묶어서 보여줄 때.

7. EditorGUILayout.BeginHorizontal();
... // 가로로 배치
- EditorGUILayout.EndHorizontal();

 

  • 역할: 필드들을 가로 방향으로 나란히 표시.
  • 사용 예: 버튼 2개 나란히 표시할 때.

8. EditorGUILayout.Space(); // 간격 추가
9. EditorGUILayout.Separator(); // 얇은 라인

역할: UI를 좀 더 보기 좋게 정리할 때.

 

10. if (GUILayout.Button("버튼 이름"))
{
    // 클릭 시 처리
}

 

  • 역할: 버튼 클릭 처리.
  • GUILayout.Button은 자동 레이아웃.
  • 사용 예: "Add", "Remove", "Reset" 같은 기능용 버튼.

11. myFoldout = EditorGUILayout.Foldout(myFoldout, "접히는 영역");

 

  • 역할: 열고 닫는 영역 만들기 (접기/펼치기).
  • 사용 예: 여러 설정을 숨기고 펼치는 UI 만들기.

 

 

 

 

 

 

 

 

 

728x90