关于 ui-imgui
面向 Unity 旧版 IMGUI 代码的维护与创建技能,涵盖编辑器窗口、自定义检查器、属性绘制器和运行时调试叠层。强调遵循项目规范、使用序列化属性,并为新的编辑器 UI 考虑 UI Toolkit。
主要功能
- 01旧版 IMGUI 代码指引
- 02编辑器窗口与检查器模式
- 03属性绘制器和调试叠层支持
- 04布局与 GUI 元素说明
- 05序列化属性及撤销实践
适用场景
- 01更新现有 OnGUI 编辑器工具
- 02按明确需求构建 IMGUI 检查器
- 03添加运行时调试叠层
- 04维护旧版 PropertyDrawer
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ unity-technologies/ skills --skill ui-imgui安装后在 Claude Code 中输入/ui-imgui确认已加载。
附带文件references/gui-elements.mdreferences/templates.md
详细介绍
开始之前: 如果用户询问要创建一个新的编辑器窗口、自定义检查器或 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 的情况 |
| PropertyDrawer(IMGUI) | 带有 OnGUI() 的 PropertyDrawer | 仅限明确要求使用 IMGUI 的情况 |
| 调试叠加层 | 带有 OnGUI() 的 MonoBehaviour | 运行时调试 |
| 更新现有 IMGUI 脚本 | 修改现有 OnGUI 代码 | 始终适用 |
如果存在歧义,请先确认:
- “inspector” → 针对特定类型的 Custom Editor,还是 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 |
| Custom Editor | [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] → 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
关键规则
- 缓存 GUIStyle 对象——切勿在 OnGUI 中创建新的 GUIStyle(每帧都会造成内存分配)
- 使用 SerializedProperty——确保检查器支持正确的撤销/重做
- 调用 ApplyModifiedProperties()——在任何序列化对象更改后调用
- 使用 EditorGUILayout——用于编辑器脚本(自动布局)
- 使用 GUILayout——用于运行时 OnGUI
- 匹配 Begin/End 调用——始终确保 BeginHorizontal 与 EndHorizontal 等成对使用
- 必须放在 Editor 文件夹中——否则脚本会导致构建失败
布局基础
水平分组:
EditorGUILayout.BeginHorizontal();
// elements appear side by side
EditorGUILayout.EndHorizontal();
垂直分组:
EditorGUILayout.BeginVertical("box");
// elements appear stacked, with box style
EditorGUILayout.EndVertical();
滚动视图:
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// scrollable content
EditorGUILayout.EndScrollView();
折叠区域:
showSection = EditorGUILayout.Foldout(showSection, "Section Name");
if (showSection)
{
EditorGUI.indentLevel++;
// section content
EditorGUI.indentLevel--;
}
常见模式
带操作的按钮:
if (GUILayout.Button("Do Something"))
{
// action here
}
带标签的属性字段:
EditorGUILayout.PropertyField(myProperty, new GUIContent("Label"));
对象引用字段:
myObject = (MyType)EditorGUILayout.ObjectField("Label", myObject, typeof(MyType), true);
禁用组:
EditorGUI.BeginDisabledGroup(condition);
// disabled elements
EditorGUI.EndDisabledGroup();
最佳实践
- 使用
SerializedObject和SerializedProperty支持撤销 - 在
OnEnable()中缓存属性引用 - 仅对非序列化更改使用
EditorUtility.SetDirty() - 直接修改对象前,使用
Undo.RecordObject() - 使用
EditorStyles保持外观一致 - 使用
GUILayout.FlexibleSpace()拉开元素间距
完整的脚本模板请参阅 references/templates.md。
完整的元素参考请参阅 references/gui-elements.md。
评论
支持 Markdown