Before proceeding: If the user is asking about creating a new editor window, custom inspector, or PropertyDrawer without explicitly mentioning IMGUI/OnGUI, recommend using UI Toolkit (CreateGUI) instead, as it's the modern approach. Only proceed with IMGUI if:
- User is modifying existing IMGUI code
- User explicitly requests IMGUI/immediate mode
- The project exclusively uses IMGUI for editor tools
When activated, read the reference files:
- [references/templates.md](references/templates.md) — EditorWindow, Inspector, PropertyDrawer templates
- [references/gui-elements.md](references/gui-elements.md) — GUI elements, layout groups, styling
When to Use This Skill
IMPORTANT: This skill is for legacy IMGUI code only. Use this skill when:
- User is maintaining/updating existing IMGUI editor code (files with
OnGUI(), OnInspectorGUI())
- User explicitly requests IMGUI/immediate mode GUI
- Project exclusively uses IMGUI for all editor tools
Do NOT use this skill for:
- New editor windows (use UI Toolkit with
CreateGUI() instead)
- New custom inspectors (use UI Toolkit instead)
- Requests that don't explicitly mention IMGUI or OnGUI
Legacy IMGUI is used for:
- Editor windows —
EditorWindow classes with OnGUI()
- Custom inspectors —
Editor, PropertyDrawer classes with OnInspectorGUI()
- Debug overlays —
OnGUI() in MonoBehaviour (runtime)
IMGUI is not for runtime game UI — use UI Toolkit or uGUI instead.
Scope
Generate only what is requested (for legacy IMGUI code):
| Request |
Output |
Note |
| Editor window (IMGUI/OnGUI) |
EditorWindow with OnGUI() |
Only if explicitly IMGUI |
| Custom inspector (IMGUI) |
Editor with OnInspectorGUI() |
Only if explicitly IMGUI |
| Property drawer (IMGUI) |
PropertyDrawer with OnGUI() |
Only if explicitly IMGUI |
| Debug overlay |
MonoBehaviour with OnGUI() |
Runtime debugging |
| Update existing IMGUI script |
Modify existing OnGUI code |
Always appropriate |
Clarify if ambiguous:
- "inspector" → Custom Editor for a specific type, or PropertyDrawer? Also ask: Should this use UI Toolkit (modern) or IMGUI (legacy)?
- "editor window" → First ask: Should this use UI Toolkit (modern/CreateGUI) or IMGUI (legacy/OnGUI)?
- "tool window" → EditorWindow with what functionality? Which UI system?
Conventions
Follow project patterns first. Search existing editor scripts before applying defaults.
| Type |
Convention |
Good |
Bad |
| Script names |
PascalCase |
MyToolWindow.cs |
my-tool-window.cs |
| EditorWindow |
[Name]Window.cs |
LevelEditorWindow.cs |
LevelEditor.cs |
| Custom Editor |
[Type]Editor.cs |
EnemyEditor.cs |
EnemyInspector.cs |
| PropertyDrawer |
[Type]Drawer.cs |
RangeDrawer.cs |
RangePropertyDrawer.cs |
| Location |
Editor folder |
Assets/Editor/ |
Assets/Scripts/ |
Editor folder is required — Scripts using UnityEditor namespace must be in an Editor folder or they will fail to build.
Workflow
- Analyze — Determine script type needed (EditorWindow, Editor, PropertyDrawer, etc.)
- Search — Find existing editor scripts to match patterns
- Follow project patterns — Match folder structure and naming
- Create script — Use appropriate base class and attributes
- Implement OnGUI — Build the interface with layout groups
Script Structure
EditorWindow
[MenuItem attribute] → adds to menu
ShowWindow() static method → opens window
OnGUI() → draws interface
OnEnable/OnDisable → initialization/cleanup
Custom Editor
[CustomEditor attribute] → targets component type
OnInspectorGUI() → draws inspector
OnEnable() → cache SerializedProperties
serializedObject.Update/ApplyModifiedProperties → undo support
PropertyDrawer
[CustomPropertyDrawer attribute] → targets type or attribute
OnGUI(Rect, SerializedProperty, GUIContent) → draws property
GetPropertyHeight() → custom height if needed
Key Rules
- Cache GUIStyle objects — never create new GUIStyle in OnGUI (causes memory allocation every frame)
- Use SerializedProperty — for proper undo/redo support in inspectors
- Call ApplyModifiedProperties() — after any serialized object changes
- Use EditorGUILayout — for editor scripts (auto-layout)
- Use GUILayout — for runtime OnGUI
- Begin/End pairs — always match BeginHorizontal with EndHorizontal, etc.
- Editor folder required — scripts fail to build if not in Editor folder
Layout Basics
Horizontal grouping:
EditorGUILayout.BeginHorizontal();
// elements appear side by side
EditorGUILayout.EndHorizontal();
Vertical grouping:
EditorGUILayout.BeginVertical("box");
// elements appear stacked, with box style
EditorGUILayout.EndVertical();
Scroll view:
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// scrollable content
EditorGUILayout.EndScrollView();
Foldout section:
showSection = EditorGUILayout.Foldout(showSection, "Section Name");
if (showSection)
{
EditorGUI.indentLevel++;
// section content
EditorGUI.indentLevel--;
}
Common Patterns
Button with action:
if (GUILayout.Button("Do Something"))
{
// action here
}
Property field with label:
EditorGUILayout.PropertyField(myProperty, new GUIContent("Label"));
Object reference field:
myObject = (MyType)EditorGUILayout.ObjectField("Label", myObject, typeof(MyType), true);
Disabled group:
EditorGUI.BeginDisabledGroup(condition);
// disabled elements
EditorGUI.EndDisabledGroup();
Best Practices
- Use
SerializedObject and SerializedProperty for undo support
- Cache property references in
OnEnable()
- Use
EditorUtility.SetDirty() only for non-serialized changes
- Use
Undo.RecordObject() before modifying objects directly
- Use
EditorStyles for consistent appearance
- Use
GUILayout.FlexibleSpace() to push elements apart
See references/templates.md for complete script templates. See references/gui-elements.md for full element reference.