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 — EditorWindow, Inspector, PropertyDrawer templates
- 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 , )
- 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 instead)
- New custom inspectors (use UI Toolkit instead)
- Requests that don't explicitly mention IMGUI or OnGUI
Legacy IMGUI is used for:
- Editor windows — classes with
- Custom inspectors — , classes with
- Debug overlays — 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) | with | Only if explicitly IMGUI |
| Custom inspector (IMGUI) | with | Only if explicitly IMGUI |
| Property drawer (IMGUI) | with | Only if explicitly IMGUI |
| Debug overlay | with | 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 | | |
| EditorWindow | | | |
| Custom Editor | | | |
| PropertyDrawer | | | |
| Location | folder | | |
Editor folder is required — Scripts using
namespace must be in an
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:
csharp
EditorGUILayout.BeginHorizontal();
// elements appear side by side
EditorGUILayout.EndHorizontal();
Vertical grouping:
csharp
EditorGUILayout.BeginVertical("box");
// elements appear stacked, with box style
EditorGUILayout.EndVertical();
Scroll view:
csharp
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// scrollable content
EditorGUILayout.EndScrollView();
Foldout section:
csharp
showSection = EditorGUILayout.Foldout(showSection, "Section Name");
if (showSection)
{
EditorGUI.indentLevel++;
// section content
EditorGUI.indentLevel--;
}
Common Patterns
Button with action:
csharp
if (GUILayout.Button("Do Something"))
{
// action here
}
Property field with label:
csharp
EditorGUILayout.PropertyField(myProperty, new GUIContent("Label"));
Object reference field:
csharp
myObject = (MyType)EditorGUILayout.ObjectField("Label", myObject, typeof(MyType), true);
Disabled group:
csharp
EditorGUI.BeginDisabledGroup(condition);
// disabled elements
EditorGUI.EndDisabledGroup();
Best Practices
- Use and for undo support
- Cache property references in
- Use only for non-serialized changes
- Use before modifying objects directly
- Use for consistent appearance
- Use
GUILayout.FlexibleSpace()
to push elements apart
See
for complete script templates.
See
references/gui-elements.md
for full element reference.