SKILL.md
只读
名称
ui-imgui
描述
Unity IMGUI(即时模式GUI)专家,专注于使用OnGUI/即时模式的旧版编辑器工具。生成和修改IMGUI EditorWindows、自定义Inspectors、PropertyDrawers以及包含IMGUI代码(OnGUI、OnInspectorGUI)的脚本。在维护现有IMGUI编辑器代码或用户明确要求IMGUI/OnGUI时使用。
开始之前: 如果用户要求创建新的编辑器窗口、自定义检查器或PropertyDrawer,且未明确提及IMGUI/OnGUI,建议使用UI Toolkit(CreateGUI),因为这是现代方法。仅在以下情况使用IMGUI:
- 用户正在修改现有的IMGUI代码
- 用户明确要求IMGUI/即时模式
- 项目仅使用IMGUI进行编辑器工具开发
激活后,请阅读参考文件:
- references/templates.md — EditorWindow、Inspector、PropertyDrawer模板
- references/gui-elements.md — GUI元素、布局组、样式
何时使用此技能
重要: 此技能仅用于旧版IMGUI代码。在以下情况使用此技能:
- 用户正在维护/更新现有的IMGUI编辑器代码(包含
OnGUI()、OnInspectorGUI()的文件) - 用户明确要求IMGUI/即时模式GUI
- 项目仅使用IMGUI进行所有编辑器工具开发
不要将此技能用于:
- 新的编辑器窗口(改用UI Toolkit,使用
CreateGUI()) - 新的自定义检查器(改用UI Toolkit)
- 未明确提及IMGUI或OnGUI的请求
旧版IMGUI用于:
- 编辑器窗口 — 包含
OnGUI()的EditorWindow类 - 自定义检查器 — 包含
OnInspectorGUI()的Editor、PropertyDrawer类 - 调试覆盖层 — MonoBehaviour中的
OnGUI()(运行时)
IMGUI不用于运行时游戏UI — 请改用UI Toolkit或uGUI。
范围
仅生成所请求的内容(针对旧版IMGUI代码):
| 请求 | 输出 | 注意 |
|---|---|---|
| 编辑器窗口(IMGUI/OnGUI) | 包含OnGUI()的EditorWindow |
仅当明确要求IMGUI时 |
| 自定义检查器(IMGUI) | 包含OnInspectorGUI()的Editor |
仅当明确要求IMGUI时 |
| 属性绘制器(IMGUI) | 包含OnGUI()的PropertyDrawer |
仅当明确要求IMGUI时 |
| 调试覆盖层 | 包含OnGUI()的MonoBehaviour |
运行时调试 |
| 更新现有IMGUI脚本 | 修改现有的OnGUI代码 | 始终适用 |
如果含义不明确,请澄清:
- "inspector" → 特定类型的自定义编辑器,还是PropertyDrawer?同时询问: 应该使用UI Toolkit(现代)还是IMGUI(旧版)?
- "editor window" → 首先询问: 应该使用UI Toolkit(现代/CreateGUI)还是IMGUI(旧版/OnGUI)?
- "tool window" → EditorWindow需要什么功能?使用哪种UI系统?
约定
首先遵循项目模式。 在应用默认值之前,搜索现有的编辑器脚本。
| 类型 | 约定 | 好 | 坏 |
|---|---|---|---|
| 脚本名称 | PascalCase | MyToolWindow.cs |
my-tool-window.cs |
| EditorWindow | [Name]Window.cs |
LevelEditorWindow.cs |
LevelEditor.cs |
| 自定义编辑器 | [Type]Editor.cs |
EnemyEditor.cs |
EnemyInspector.cs |
| PropertyDrawer | [Type]Drawer.cs |
RangeDrawer.cs |
RangePropertyDrawer.cs |
| 位置 | Editor文件夹 |
Assets/Editor/ |
Assets/Scripts/ |
Editor文件夹是必需的 — 使用UnityEditor命名空间的脚本必须放在Editor文件夹中,否则将无法构建。
工作流程
- 分析 — 确定所需的脚本类型(EditorWindow、Editor、PropertyDrawer等)
- 搜索 — 查找现有的编辑器脚本以匹配模式
- 遵循项目模式 — 匹配文件夹结构和命名
- 创建脚本 — 使用适当的基类和属性
- 实现OnGUI — 使用布局组构建界面
脚本结构
EditorWindow
[MenuItem attribute] → 添加到菜单
ShowWindow() 静态方法 → 打开窗口
OnGUI() → 绘制界面
OnEnable/OnDisable → 初始化/清理
自定义编辑器
[CustomEditor attribute] → 目标组件类型
OnInspectorGUI() → 绘制检查器
OnEnable() → 缓存SerializedProperties
serializedObject.Update/ApplyModifiedProperties → 撤销支持
PropertyDrawer
[CustomPropertyDrawer attribute] → 目标类型或属性
OnGUI(Rect, SerializedProperty, GUIContent) → 绘制属性
GetPropertyHeight() → 自定义高度(如果需要)
关键规则
- 缓存GUIStyle对象 — 不要在OnGUI中创建新的GUIStyle(会导致每帧内存分配)
- 使用SerializedProperty — 以便在检查器中正确支持撤销/重做
- 调用ApplyModifiedProperties() — 在序列化对象更改后
- 使用EditorGUILayout — 用于编辑器脚本(自动布局)
- 使用GUILayout — 用于运行时OnGUI
- Begin/End配对 — 始终将BeginHorizontal与EndHorizontal匹配,等等。
- Editor文件夹必需 — 脚本不在Editor文件夹中将无法构建
布局基础
水平分组:
EditorGUILayout.BeginHorizontal();
// 元素并排显示
EditorGUILayout.EndHorizontal();
垂直分组:
EditorGUILayout.BeginVertical("box");
// 元素堆叠显示,带框样式
EditorGUILayout.EndVertical();
滚动视图:
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// 可滚动内容
EditorGUILayout.EndScrollView();
折叠区段:
showSection = EditorGUILayout.Foldout(showSection, "Section Name");
if (showSection)
{
EditorGUI.indentLevel++;
// 区段内容
EditorGUI.indentLevel--;
}
常见模式
带操作的按钮:
if (GUILayout.Button("Do Something"))
{
// 此处执行操作
}
带标签的属性字段:
EditorGUILayout.PropertyField(myProperty, new GUIContent("Label"));
对象引用字段:
myObject = (MyType)EditorGUILayout.ObjectField("Label", myObject, typeof(MyType), true);
禁用组:
EditorGUI.BeginDisabledGroup(condition);
// 禁用的元素
EditorGUI.EndDisabledGroup();
最佳实践
- 使用
SerializedObject和SerializedProperty以支持撤销 - 在
OnEnable()中缓存属性引用 - 仅对非序列化更改使用
EditorUtility.SetDirty() - 在直接修改对象之前使用
Undo.RecordObject() - 使用
EditorStyles保持外观一致 - 使用
GUILayout.FlexibleSpace()分隔元素
参见references/templates.md获取完整脚本模板。
参见references/gui-elements.md获取完整元素参考。






