ui-imgui
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBefore 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
开始之前: 如果用户询问创建新编辑器窗口、自定义Inspector或PropertyDrawer但未明确提及IMGUI/OnGUI,建议使用UI Toolkit(CreateGUI),这是现代方案。仅在以下情况使用IMGUI:
- 用户正在修改现有IMGUI代码
- 用户明确要求使用IMGUI/即时模式
- 项目的编辑器工具完全基于IMGUI
激活后,请阅读参考文件:
- references/templates.md — EditorWindow、Inspector、PropertyDrawer模板
- references/gui-elements.md — GUI元素、布局组、样式
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 instead)
CreateGUI() - 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
EditorWindowOnGUI() - Custom inspectors — ,
Editorclasses withPropertyDrawerOnInspectorGUI() - Debug overlays — in MonoBehaviour (runtime)
OnGUI()
IMGUI is not for runtime game UI — use UI Toolkit or uGUI instead.
重要提示: 此技能仅适用于遗留IMGUI代码。在以下情况使用:
- 用户正在维护/更新现有IMGUI编辑器代码(包含、
OnGUI()的文件)OnInspectorGUI() - 用户明确要求使用IMGUI/即时模式GUI
- 项目所有编辑器工具均完全使用IMGUI
请勿在以下场景使用此技能:
- 新编辑器窗口(改用基于的UI Toolkit)
CreateGUI() - 新自定义Inspector(改用UI Toolkit)
- 未明确提及IMGUI或OnGUI的需求
遗留IMGUI的适用场景:
- 编辑器窗口 — 包含的
OnGUI()类EditorWindow - 自定义Inspector — 包含的
OnInspectorGUI()、Editor类PropertyDrawer - 调试叠加层 — MonoBehaviour中的(运行时)
OnGUI()
IMGUI不适用于运行时游戏UI — 请改用UI Toolkit或uGUI。
Scope
范围
Generate only what is requested (for legacy IMGUI code):
| Request | Output | Note |
|---|---|---|
| Editor window (IMGUI/OnGUI) | | Only if explicitly IMGUI |
| Custom inspector (IMGUI) | | Only if explicitly IMGUI |
| Property drawer (IMGUI) | | Only if explicitly IMGUI |
| Debug overlay | | 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?
仅生成符合需求的内容(针对遗留IMGUI代码):
| 请求 | 输出 | 说明 |
|---|---|---|
| 编辑器窗口(IMGUI/OnGUI) | 包含 | 仅当明确指定使用IMGUI时 |
| 自定义Inspector(IMGUI) | 包含 | 仅当明确指定使用IMGUI时 |
| PropertyDrawer(IMGUI) | 包含 | 仅当明确指定使用IMGUI时 |
| 调试叠加层 | 包含 | 运行时调试 |
| 更新现有IMGUI脚本 | 修改现有OnGUI代码 | 始终适用 |
若需求模糊,请澄清:
- "inspector" → 是针对特定类型的Custom Editor,还是PropertyDrawer?同时询问: 应使用UI Toolkit(现代)还是IMGUI(遗留)?
- "editor window" → 首先询问: 应使用UI Toolkit(现代/CreateGUI)还是IMGUI(遗留/OnGUI)?
- "tool window" → EditorWindow需要具备什么功能?使用哪个UI系统?
Conventions
约定
Follow project patterns first. Search existing editor scripts before applying defaults.
| Type | Convention | Good | Bad |
|---|---|---|---|
| Script names | PascalCase | | |
| EditorWindow | | | |
| Custom Editor | | | |
| PropertyDrawer | | | |
| Location | | | |
Editor folder is required — Scripts using namespace must be in an folder or they will fail to build.
UnityEditorEditor优先遵循项目模式。在应用默认规则前,先搜索现有编辑器脚本。
| 类型 | 约定 | 规范示例 | 不规范示例 |
|---|---|---|---|
| 脚本名称 | PascalCase | | |
| EditorWindow | | | |
| Custom Editor | | | |
| PropertyDrawer | | | |
| 存放位置 | | | |
必须放在Editor文件夹 — 使用命名空间的脚本必须放在文件夹中,否则构建会失败。
UnityEditorEditorWorkflow
工作流程
- 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
- 分析 — 确定所需脚本类型(EditorWindow、Editor、PropertyDrawer等)
- 搜索 — 查找现有编辑器脚本以匹配项目模式
- 遵循项目模式 — 匹配文件夹结构和命名规则
- 创建脚本 — 使用合适的基类和特性
- 实现OnGUI — 使用布局组构建界面
Script Structure
脚本结构
EditorWindow
EditorWindow
[MenuItem attribute] → adds to menu
ShowWindow() static method → opens window
OnGUI() → draws interface
OnEnable/OnDisable → initialization/cleanup[MenuItem特性] → 添加到菜单
ShowWindow()静态方法 → 打开窗口
OnGUI() → 绘制界面
OnEnable/OnDisable → 初始化/清理Custom Editor
Custom Editor
[CustomEditor attribute] → targets component type
OnInspectorGUI() → draws inspector
OnEnable() → cache SerializedProperties
serializedObject.Update/ApplyModifiedProperties → undo support[CustomEditor特性] → 目标组件类型
OnInspectorGUI() → 绘制Inspector
OnEnable() → 缓存SerializedProperties
serializedObject.Update/ApplyModifiedProperties → 撤销支持PropertyDrawer
PropertyDrawer
[CustomPropertyDrawer attribute] → targets type or attribute
OnGUI(Rect, SerializedProperty, GUIContent) → draws property
GetPropertyHeight() → custom height if needed[CustomPropertyDrawer特性] → 目标类型或特性
OnGUI(Rect, SerializedProperty, GUIContent) → 绘制属性
GetPropertyHeight() → 按需自定义高度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
- 缓存GUIStyle对象 — 绝不要在OnGUI中创建新的GUIStyle(会导致每帧内存分配)
- 使用SerializedProperty — 为Inspector提供正确的撤销/重做支持
- 调用ApplyModifiedProperties() — 在任何序列化对象更改后调用
- 使用EditorGUILayout — 用于编辑器脚本(自动布局)
- 使用GUILayout — 用于运行时OnGUI
- 成对使用Begin/End — 始终确保BeginHorizontal与EndHorizontal等成对出现
- 必须放在Editor文件夹 — 脚本若不在Editor文件夹中会导致构建失败
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--;
}水平分组:
csharp
EditorGUILayout.BeginHorizontal();
// 元素并排显示
EditorGUILayout.EndHorizontal();垂直分组:
csharp
EditorGUILayout.BeginVertical("box");
// 元素堆叠显示,带box样式
EditorGUILayout.EndVertical();滚动视图:
csharp
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// 可滚动内容
EditorGUILayout.EndScrollView();折叠区域:
csharp
showSection = EditorGUILayout.Foldout(showSection, "Section Name");
if (showSection)
{
EditorGUI.indentLevel++;
// 区域内容
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();带操作的按钮:
csharp
if (GUILayout.Button("Do Something"))
{
// 此处添加操作
}带标签的属性字段:
csharp
EditorGUILayout.PropertyField(myProperty, new GUIContent("Label"));对象引用字段:
csharp
myObject = (MyType)EditorGUILayout.ObjectField("Label", myObject, typeof(MyType), true);禁用组:
csharp
EditorGUI.BeginDisabledGroup(condition);
// 禁用的元素
EditorGUI.EndDisabledGroup();Best Practices
最佳实践
- Use and
SerializedObjectfor undo supportSerializedProperty - Cache property references in
OnEnable() - Use only for non-serialized changes
EditorUtility.SetDirty() - Use before modifying objects directly
Undo.RecordObject() - Use for consistent appearance
EditorStyles - Use to push elements apart
GUILayout.FlexibleSpace()
See for complete script templates.
See for full element reference.
references/templates.mdreferences/gui-elements.md- 使用和
SerializedObject以获得撤销支持SerializedProperty - 在中缓存属性引用
OnEnable() - 仅对非序列化更改使用
EditorUtility.SetDirty() - 直接修改对象前调用
Undo.RecordObject() - 使用以保持外观一致
EditorStyles - 使用来分隔元素
GUILayout.FlexibleSpace()
完整脚本模板请查看。
完整元素参考请查看。
references/templates.mdreferences/gui-elements.md