Unity 에디터 커스텀 윈도우
EditorWindow 기본 구조
섹션 제목: “EditorWindow 기본 구조”using UnityEditor;using UnityEngine;
public class MyToolWindow : EditorWindow { [MenuItem("Tools/My Tool")] public static void ShowWindow() { GetWindow<MyToolWindow>("My Tool"); }
string _searchQuery = ""; Vector2 _scroll;
void OnGUI() { EditorGUILayout.LabelField("My Tool", EditorStyles.boldLabel); _searchQuery = EditorGUILayout.TextField("검색", _searchQuery);
_scroll = EditorGUILayout.BeginScrollView(_scroll); // 콘텐츠 EditorGUILayout.EndScrollView();
if (GUILayout.Button("실행")) Execute(); }
void Execute() { /* ... */ }}SerializedObject로 Undo 지원
섹션 제목: “SerializedObject로 Undo 지원”직접 필드를 수정하면 Undo가 동작하지 않습니다. SerializedObject를 경유하면 Undo/Redo, Prefab Override가 자동 지원됩니다.
[CustomEditor(typeof(EnemyData))]public class EnemyDataEditor : Editor { SerializedProperty _hp; SerializedProperty _speed;
void OnEnable() { _hp = serializedObject.FindProperty("hp"); _speed = serializedObject.FindProperty("speed"); }
public override void OnInspectorGUI() { serializedObject.Update(); // 최신값 로드
EditorGUILayout.PropertyField(_hp, new GUIContent("체력")); EditorGUILayout.PropertyField(_speed, new GUIContent("속도"));
if (serializedObject.hasModifiedProperties) serializedObject.ApplyModifiedProperties(); // 변경 커밋 + Undo 등록 }}PropertyDrawer로 인스펙터 커스터마이징
섹션 제목: “PropertyDrawer로 인스펙터 커스터마이징”[System.Serializable]public struct Range { public float Min; public float Max; }
[CustomPropertyDrawer(typeof(Range))]public class RangeDrawer : PropertyDrawer { public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label) { EditorGUI.BeginProperty(pos, label, prop); pos = EditorGUI.PrefixLabel(pos, label);
float half = pos.width / 2f - 2f; var minProp = prop.FindPropertyRelative("Min"); var maxProp = prop.FindPropertyRelative("Max");
EditorGUI.PropertyField(new Rect(pos.x, pos.y, half, pos.height), minProp, GUIContent.none); EditorGUI.PropertyField(new Rect(pos.x+half+4, pos.y, half, pos.height), maxProp, GUIContent.none);
EditorGUI.EndProperty(); }}UI Toolkit (UIElements) 방식
섹션 제목: “UI Toolkit (UIElements) 방식”Unity 2021+에서 권장되는 방식으로 UXML + USS로 레이아웃을 구성합니다.
public class MyToolWindow : EditorWindow { [MenuItem("Tools/My Tool (UIToolkit)")] public static void ShowWindow() => GetWindow<MyToolWindow>();
public void CreateGUI() { // UXML 로드 var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>( "Assets/Editor/MyTool.uxml"); uxml.CloneTree(rootVisualElement);
// 요소 참조 및 이벤트 등록 var btn = rootVisualElement.Q<Button>("execute-btn"); btn.clicked += Execute;
var field = rootVisualElement.Q<TextField>("search-field"); field.RegisterValueChangedCallback(e => OnSearchChanged(e.newValue)); }
void Execute() { } void OnSearchChanged(string query) { }}에디터 유틸리티 모음
섹션 제목: “에디터 유틸리티 모음”// 씬의 특정 컴포넌트 전체 검색static T[] FindAllInScene<T>() where T : Component => Object.FindObjectsByType<T>(FindObjectsSortMode.None);
// 에셋 생성static T CreateAsset<T>(string path) where T : ScriptableObject { var asset = ScriptableObject.CreateInstance<T>(); AssetDatabase.CreateAsset(asset, path); AssetDatabase.SaveAssets(); return asset;}
// 선택된 오브젝트에 컴포넌트 일괄 추가[MenuItem("Tools/Add Rigidbody to Selection")]static void AddRigidbody() { foreach (var go in Selection.gameObjects) { Undo.AddComponent<Rigidbody>(go); }}EditorPrefs로 설정 저장
섹션 제목: “EditorPrefs로 설정 저장”const string PrefKey = "MyTool_SearchQuery";
void OnEnable() => _searchQuery = EditorPrefs.GetString(PrefKey, "");void OnDisable() => EditorPrefs.SetString(PrefKey, _searchQuery);EditorWindow로 독립 윈도우,Editor/PropertyDrawer로 인스펙터 커스텀SerializedObject+ApplyModifiedProperties로 Undo/Prefab Override 자동 지원- UI Toolkit(UIElements)이 Unity 2021+에서 권장 방식
EditorPrefs로 개발자별 설정 유지Undo.AddComponent,Undo.RecordObject로 에디터 조작에 Undo 지원