[Unity, C#] Editor - 커스텀 인스펙터

2025. 8. 2. 18:14·Unity,C#/Unity 정보
728x90

 ■ Editor - 커스텀 인스펙터

public class SizeController : MonoBehaviour
{
	// Do Something...
}

유니티에서 MonoBehaviour를 상속받는 스크립트는 게임 오브젝트에 부착할 수 있으며, 부착 시 모든 public 필드와 [SerializeField] 변수를 인스펙터에 자동으로 노출한다.

 

하지만 이러한 기본 기능 외에도, 버튼을 눌러 특정 함수를 실행하거나, 에디터 모드(Edit Mode)에서도 실시간으로 값을 반영하고 조작하고 싶을 때가 있다.

  • 이럴 때 CustomEditor를 사용하면 원하는 형태로 인스펙터를 자유롭게 커스터마이징 할 수 있다.

 

1. Custom Editor 생성

public class SizeController : MonoBehaviour
{
    [SerializeField] private GameObject obj;
    [SerializeField] private Vector3 scale;
    
    public void ChangeScale()
    {
        obj.transform.localScale = scale;
    }

    private void Update()
    {
        ChangeScale();
    }
}

[SizeController.cs]

위 스크립트는 인스펙터에서 값을 수정하면 해당 오브젝트의 크기를 바꾸는 아주 단순한 스크립트이다.

 

다만, 이 스크립트는 Updata()를 통해 실행되므로 오직 Play Mode에서만 동작하며, 에디터 모드로 돌아오면 변경한 값이 실제 오브젝트에 반영되지 않는다.

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(SizeController))]
public class SizeControlEditor : Editor
{
    private SerializedProperty _scaleProp;
    
    private void OnEnable()
    {
        _scaleProp = serializedObject.FindProperty("scale");
    }

    public override void OnInspectorGUI()
    {
        var sizeController = (SizeController)target;

				// 기존 인스펙터를 그리는 함수
        DrawDefaultInspector();

        if (GUILayout.Button("Apply"))
        {
            sizeController.ChangeScale();
        }
    }
}

CustomEditor는 Unity의 Editor 클래스를 상속받아 작성하며, 인스펙터를 직접 커스터마이즈 할 수 있도록 해준다.

이러한 스크립트는 반드시 Editor 전용 폴더(예 : Assets/Editor) 내에 위치해야 한다.

  • UnityEditor 네임스페이스는 런타임이 아닌 에디터 전용 API를 포함하므로, Unity의 빌드 대상에는 포함되지 않아야 한다. Unity는 자동으로 Editor 폴더 내 스크립트를 제외하기 때문에 커스텀 에디터 스크립트는 항상 Editor 폴더에 작성해야 한다.

 

2. Editor 추상 클래스

커스텀 에디터를 구현하기 위해선 Editor 추상 클래스를 상속받아야 한다. 이 클래스의 구성 요소는 아래와 같다.

항목 설명
OnEnable() 인스펙터 창을 클릭하면 처음으로 한번 호출되는 함수.
OnInspectorGUI() 인스펙터 창에 어떤 UI 요소를 보여줄지 정의하며, 인스펙터가 그려질 때마다 자동으로 호출된다.
DrawDefaultInspector() 기존 인스펙터 UI를 출력하는 함수.

 

1. target 프로퍼티

[target 프로퍼티]

target은 현재 커스텀 에디터가 편집 중인 컴포넌트 인스턴스를 가리킨다. 즉, 오브젝트 자체가 아니라 그 오브젝트의 붙은 스크립트 컴포넌트를 참조한다.

[CustomEditor(typeof(SizeController))]

 

위와 같이 CustomEditor 어트리뷰트로 대상 타입을 지정하면, Unity는 해당 에디터가 SizeController용이라는 것을 인식하고, 해당 컴포넌트를 target에 자동으로 할당한다.

  • 따라서 new나 GetComponent<>() 호출 없이 사용할 수 있다.
  • target은 UnityEngin.Object 타입이므로, 사용 시 명시적 캐스팅이 필요하다.

 

public override void OnInspectorGUI()
{
	var sizeController = (SizeController)target;
	
	DrawDefaultInspector();
	
	if (GUILayout.Button("Apply"))
	{
		sizeController.ChangeScale();
	}
}

위와 같이 target을 통해 연결된 컴포넌트 인스턴스를 가져오면, 그 내부에 정의된 함수를 직접 호출하는 것도 가능하다.

  • 버튼을 만들고 클릭하면, ChangeScale() 함수가 실행되어 인스펙터에서 설정한 값을 적용할 수 있다.

 

2. SerializedProperty

SerializedProperty는 직렬화된 데이터를 안전하게 조작할 수 있도록 감싼 객체이다.

직렬화된 필드를 직접 수정하는 대신, SerializedProperty를 통해 간접적으로 접근할 수 있게 함으로써 Undo/Redo, 멀티 오브젝트 편집, 프리팹 동기화 같은 기능을 안전하게 처리할 수 있다.


[CustomEditor(typeof(SizeController))]
public class SizeControlEditor : Editor
{
    private SerializedProperty _scaleProp;
    
    private void OnEnable()
    {
        _scaleProp = serializedObject.FindProperty("scale");
    }

    public override void OnInspectorGUI()
    {
        var sizeController = (SizeController)target;

        DrawDefaultInspector();
        
        // 1. 현재 에디터 대상 오브젝트(target)의 최신 값을 직렬화 시스템에 반영.
        serializedObject.Update();
        
        // SerializedProperty를 통한 접근
        if (GUILayout.Button("Apply(SerializedProperty)"))
        {
            // 2. SerializedProperty 값 설정
            _scaleProp.vector3Value = new Vector3(3, 3, 3);
        }
        
        // 3. 변경 내용 적용 (쓰기 완료)
        serializedObject.ApplyModifiedProperties();
    }
}

 

▶ serializedObject.FindProperty("이름")

직렬화된 필드를 SerializedProperty로 가져온다.

 

▶ serializedObject.Update()

직렬화 시스템의 내부 데이터를 최신 상태로 동기화한다.

인스펙터에서 scale 값을 수정하더라도, 이 값은 바로 SerializedProperty에 반영되지 않기 때문에, 수정된 내용을 정확하게 반영하려면 먼저 Update() 함수를 호출해야 한다.

 

▶serializedObject.ApplyModifiedProperties()

변경한 내용을 실제 오브젝트에 적용한다.

 

■ GUILayout

GUILayout 은 UnityEditor에서 제공하는 자동 레이아웃 기반 UI 그리기 도구이다.

  • 버튼, 텍스트, 입력 필드 등 다양한 GUI 요소를 좌표 계산 없이 자동으로 배치해 준다.
  • OnInspectorGUI()나 OnGUI() 내부에서 사용하여 인스펙터나 커스텀 에디터 창의 UI를 구성할 수 있다.

 

함수  설명
GUILayout.Label("텍스트") 단순한 텍스트 출력
GUILayout.Button("클릭") 버튼 출력 (클릭 여부 반환)
GUILayout.TextField("내용") 텍스트 입력 필드 출력
GUILayout.Toggle(bool, "이름") 체크박스
GUILayout.Space(픽셀) 수직 여백 추가
GUILayout.BeginVertical() / EndVertical() 위아래 정렬 그룹 시작/끝
GUILayout.BeginHorizontal() / EndHorizontal() 좌우 정렬 그룹 시작/끝

이 함수들을 사용해 인스텍터 창을 직관적이고 자유롭게 구성할 수 있으며 아래 Unity 공식 문서를 참고하면 더 많은 종류의 함수를 사용할 수 있다.

 

https://docs.unity3d.com/ScriptReference/GUILayout.html

728x90

'Unity,C# > Unity 정보' 카테고리의 다른 글

[Unity, C#] ScriptableObject - 스크립터블 오브젝트  (4) 2025.08.02
[Unity, C#] EditorWindow - 커스텀 에디터 윈도우  (1) 2025.08.02
[C#] LINQ(Language Integrated Query)  (1) 2025.06.27
[Unity] Coroutine(코루틴) 파헤치기  (4) 2025.05.30
'Unity,C#/Unity 정보' 카테고리의 다른 글
  • [Unity, C#] ScriptableObject - 스크립터블 오브젝트
  • [Unity, C#] EditorWindow - 커스텀 에디터 윈도우
  • [C#] LINQ(Language Integrated Query)
  • [Unity] Coroutine(코루틴) 파헤치기
브라더스톤
브라더스톤
유티니, C#과 관련한 여러 정보를 끄적여둔 블로그입니다. Email : dkavmdk98@gmail.com
  • 브라더스톤
    젊은 프로그래머의 슬픔
    브라더스톤
  • 전체
    오늘
    어제
    • 개발 노트 (26)
      • Unity,C# (26)
        • Unity 정보 (5)
        • 알고리즘 (10)
        • 자료구조 (2)
        • 절차적생성(PCG) (9)
      • C++ (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    PerlinNoise
    CustomEditorWindow
    Custom Inspector
    절차적 던전 생성
    절차적던전생성
    최단경로찾기
    자료구조
    CustomWindow
    알고리즘
    커스텀 인스펙터
    이진공간분할
    절차적지형생성
    pcg
    정렬알고리즘
    C#
    커스텀 윈도우
    unity
    이진공간분할법
    BSP
    binary space partitioning
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
브라더스톤
[Unity, C#] Editor - 커스텀 인스펙터
상단으로

티스토리툴바