关于 scenario-unity-ui
面向 UI 开发者的 Unity 技能,支持使用 uGUI 或 UI Toolkit 构建界面。内容涵盖响应式布局、输入与焦点行为、本地化、渲染成本,并通过截图、审计和测试进行验证。
主要功能
- 01选择 uGUI 或 UI Toolkit
- 02适配不同屏幕尺寸的布局
- 03支持鼠标、触控、键盘和手柄
- 04本地化与字体字形检查
- 05UI 截图、审计和性能计数
适用场景
- 01为手机和 4K 显示器构建菜单
- 02测试不同 UI 系统间的导航与焦点
- 03检查本地化文本和缺失字形
- 04定位 UI 重建与渲染开销
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unity-ui安装后在 Claude Code 中输入/scenario-unity-ui确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/AgentKit/UI/UIAudit.csUIBuild.csUICapture.csUIPerf.csUISetup.csUIToolkitBuild.csscripts/Runtime/UI/AgentUI.Runtime.asmdefCanvasDeviceScale.csClampedWidth.csHudBar.csHudModel.csHudView.csMenuRouter.csMenuScreen.csPanelChangeLog.csRebindRow.csRebuildProbe.csScrollToSelection.csSelectableFeedback.csSettingsScreen.csSettingsService.csUiCounterSampler.csUILoader.csUiPerfDriver.csUiTheme.cs详细介绍
Unity UI(UI 开发者)
专业的 UI 工作应确保屏幕从竖屏手机到 4K 显示器都保持相同的布局,能同样响应鼠标、触摸、键盘和游戏手柄,清晰易读,并且静止时几乎不消耗资源。Agent 通过代码或文本构建界面,再为每种设备尺寸截取画面、在同一帧进行布局断言、执行审查和行为测试,并检查计数器,以此实现目标。目标版本:Unity 6000.3.21f1、uGUI 2.0(内置 TextMeshPro)、UI Toolkit、Input System 1.20。如果此处提及的同级技能不在可用技能中,请让用户安装(npx skills add scenario-labs/skills --skill <name>);若处于无人值守状态,则根据工具架构继续操作,并标明缺失项。
必备背景: scenario-unity-expert(通道、审查循环、6.3 陷阱)。工具集:scripts/ut_ui.py(导入 ut_env、ut_run、ut_review),任务位于 scripts/AgentKit/UI/,运行时组件位于 scripts/Runtime/UI/(asmdef 为 AgentUI.Runtime),UXML/USS/TSS 模板位于 scripts/templates/uitk/。
立场(专家差异)
- uGUI 仍是 6.3 运行时的推荐选择;以功能矩阵为准。 仅 UI Toolkit 支持:数据绑定、USS 过渡、灵活布局、全局样式、动态图集、RTL 和 emoji、SVG。仅 uGUI 支持:Animation Clips 和 Timeline、序列化事件、Scene 视图创作(6.3 Manual)。自定义着色器(UI Shader Graph)和世界空间在 6.3 中同时列于两栏:绝不是选择 uGUI 的理由。没有阻碍因素:保留项目当前使用的系统;UI 密集型或由设计师主导的项目倾向于选择 UI Toolkit;两栏功能都需要时,按屏幕拆分(
ut_ui.choose_system)。 - 统一参考分辨率、锚定边缘,并按方向选择 Match。 1920 x 1080,Scale With Screen Size;同时支持两种方向时,Match 设为 0.5:使用此横向参考分辨率时,Match 0 会将竖屏手机的尺寸缩小到 0.5625(Match 1 则会将其放大 1.78 倍);手册中「Match 0 时为 1.5 倍」的说法,使用的是横屏显示的竖屏参考分辨率。uGUI 在对数空间中混合 Match,UI Toolkit 则线性混合:在 1080 x 1920 下分别为 1.0 和 1.17(实测)。Game 视图显示设计分辨率时,将每个元素锚定到对应角落,并将缩放保持为 1(uGUI 手册;Christina)。通过触控目标检查为手机设置手持设备倍率(
CanvasDeviceScale,1.35)。 - uGUI Canvas 是重建和批处理的单位。 将静态内容与逐帧更新的内容拆分到子 Canvas 中;从仅用于显示的 Canvas 移除 Raycaster,并取消勾选标签上的 Raycast Target。不同 Canvas 之间永远不会合批:400 个世界空间名称牌就会产生 400 个批次(Andy Touch)。使用
Canvas.enabled隐藏(网格重生成次数为 0,而SetActive为 200 次,实测),并设置CanvasGroup.interactable,否则按钮仍可导航。 - 布局会依次解析 preferred、min,否则为 0。 若子项没有任何尺寸信息,启用 Control Child Size 后它就会折叠;Content Size Fitter 只能放在最顶层;pivot 决定扩展方向;逐帧更新的 UI 不要使用布局组。尺寸不符合预期时,查看父项和子项的 min/preferred/flexible(
UIAudit.ExplainLayout),不要切换复选框(Christina,HTQV4mukZ2M)。 - 两种系统共用一套选择规则和图层表。 悬停时选中;屏幕显示一帧后才会选中第一个选项;记住最后一次选择,供游戏手柄使用(Sasquatch B Studios)。将脚本化的
InputSystemUIInputModule指向InputSystem.actions,否则重新绑定不会影响导航(实测)。用同一张表为每个图层指定独立的排序顺序(ut_ui.UI_LAYERS:HUD 0、菜单 10、模态 20):Canvas.sortingOrder和PanelSettings.sortingOrder会相互比较(自 2021.2 起影响绘制顺序,Unity 员工确认;此处实测输入顺序);排序值相同时,顶层由 Hierarchy 顺序决定(Christina)。焦点通过 EventSystem 在两种系统间切换:element.Focus()会选中面板,SetSelectedGameObject(uguiButton)会使其失去焦点(实测)。将 UI 放在独立的附加场景中,并让该场景持有唯一的 EventSystem(Jason Weimann)。 - 文本:在材质中实现特效,每种系统使用一套字体链。 Shadow 加 Outline 会将三角形数量从 28 增至 280;TMP 的 outline 和 underlay 保持在 30(实测;Andy Touch)。TMP fallback 不会应用到 UI Toolkit 文本;后者会解析自己的字体和 Panel Text Settings:即使 TMP Settings 中有 CJK 字体,HUD 仍然无法显示「設定」(实测)。通过 tryAdd on 为每种系统启用所有语言;所有 fallback 资源使用相同的采样尺寸和内边距(约为十分之一);将 CJK 字体拆分到多个资源中;RTL 意味着应使用 UI Toolkit(Imphenzia)。由代码填充的下拉菜单应在语言环境事件触发时重新填充(
SettingsScreen.OnLocaleChanged)。 - UI Toolkit 的开销取决于 GPU 状态和隐藏时长。 每个批次最多 8 张纹理(实测为 ceil(N/8));静态面板拆分到多个顶点缓冲区后会绘制两次:增大 Vertex Budget(12k 个顶点:预算为 0 时 3 个批次,为 20000 时 1 个批次,实测);模板遮罩会打断合批,因此应预先裁切圆形小地图边框;使用 usage hints 为变换添加动画;大型容器不要切换 class;
[GeneratePropertyBag]只有同时添加程序集属性时才有效(仅有 class 会生成反射 bag,实测)(Nicolas Borromeo,Unity)。按隐藏时长选择方式:长时间隐藏时移除,中等时长隐藏时使用 display none(绑定仍会运行),闪烁时使用 opacity 或移出屏幕(ut_ui.uitk_hide_method,开销见流程 P16)。使用PanelChangeLog查找空闲失效操作;样式表会加载其引用的所有资源。 - 按实际渲染方式捕获 UI,并在同一帧进行断言。 Overlay Canvas 永远不会输出到摄像机目标(UI 像素数为 0,实测):通过隐藏摄像机上的 Screen Space Camera 捕获 uGUI;通过克隆的 PanelSettings 和
targetTexture捕获 UI Toolkit。检查每张图,包括 4K 裁剪图。
首先确定
平台和方向;输入方式;语言(CJK、RTL)以及每个字符串由哪个系统渲染;之后由谁编辑 UI;已在使用的系统;设备列表(默认:竖屏手机 1080 x 1920,420 dpi;笔记本电脑 1920 x 1080;4K);配色方案(默认:纯色中性色,加一种强调色);供各关卡共享的 UI 场景;预算(默认:空闲 HUD 不增加 GC,每帧 1 个批次,0 次面板更改)。
工作流
- 选择方案。
ut_ui.choose_system(needs, ui_heavy, existing, team)。门槛:引用阻碍因素,不以共享行作为理由,两种系统都会交付时提供分层表。 - 设置。
UISetup.ImportTmpEssentials、UISetup.AddScenesToBuild、ut_ui.add_ui_test_framework;混音器来自 scenario-unity-gameplay。门槛:存在 TMP Settings。 - 构建。
UiTheme令牌(以 8 px 为步长、一个强调色、一个标题级别;Game Dev Guide)。uGUI:UIBuild.BuildMenuScene或其辅助项。UI Toolkit:先执行ut_ui.write_uitk_templates,再执行UIToolkitBuild.BuildHud。门槛:编译错误和警告均为 0;每个样式表的ImportReport错误为 0、规则数 > 0;lint_uss/lint_uxml/lint_cs_events/lint_cs_queries检查通过。 - 捕获并断言。 对
ut_ui.shots(...)执行UICapture.CaptureUGUI/CaptureUITK,并在真实关卡中捕获 HUD。门槛:layout_verdict为空;缩放值符合公式;检查并评议样式表和 4K 裁剪图(references/critique.md);使用ExplainLayout说明布局塌陷的原因。 - 审计。 使用每种区域设置的字符串执行
UIAudit.Audit;对 UI Toolkit 文本执行UIToolkitBuild.UitkGlyphs;使用BindingSources检查数据源。门槛:两种系统中的错误、警告和缺失字形均为 0;每个源都已生成。 - 行为。 Play Mode 测试(选择、游戏手柄、隐藏屏幕、设置、重新绑定、附加场景、绑定、图层与焦点、区域设置)和 Edit Mode UI Test Framework 测试(点击、按键、绑定、查询名称)。门槛:全部通过。
- 开销。
UIPerf.HideCost、TextEffectCost、PlayModeCounters(计数器、list_markers)、PanelChangeLog。门槛:根据预算核对数值,并在每次更改前后进行核对。 - 交付时注明已验证和假设,并附上下方的交接材料包。
数值
| 数值 | 相对于 | 来源 |
|---|---|---|
| 1920 x 1080,Match 0.5 | 参考值,两个方向 | uGUI 手册;Christina |
| 1.0 / 2.0;Match 0 时为 0.5625 | 1080 x 1920 / 3840 x 2160 下的 uGUI 缩放比例 | 实测;公式 |
| 1.1701 / 1.4769 | 1080 x 1920 / 1170 x 2532 下的 UI Toolkit 缩放比例(uGUI 为 1.0 / 1.1953) | 实测 |
| 88 参考像素 x 1.35 = 119 px | 控件高度;相对于 420 dpi 下 116 px(7 mm)的目标值 | [新增] |
| 4.5:1 / 3:1 | 正文 / 大号文本的对比度 | [新增] WCAG |
| 8;256 px | 每个 UI Toolkit 批次的纹理数量(实测);演示中的动态图集尺寸筛选器 | Borromeo |
| 3 与 1 个批次 | 12,000 个顶点,Vertex Budget 为 0 与 20000 | 实测 |
| 7 / 18 ms | 模板嵌套层级 / 通过一次大型类切换执行的 Update Style | Borromeo |
| 0.87-0.99 / 0.005 ms | 每帧隐藏的绑定屏幕:display none / 已移除(可见时为 1.16-1.32) | 实测,3 次运行 |
| 2.2-3.3 ms | 重新添加已移除的 120 行屏幕(display flex 为 1.5-2.0) | 实测,3 次运行 |
| 0 与 200 | 网格重新生成次数:Canvas.enabled 与 SetActive,200 个图形 | 实测 |
| 40 到 14 | 使用 Sprite Atlas 后的批次数(关闭旋转和紧密打包) | Andy Touch |
| 0.01,100 px = 1 单位 | 世界空间画布缩放比例 | Christina,Brackeys |
| 80 / 8 | TMP 采样点大小 / 内边距 | Imphenzia |
质量门槛
- 可测量: 编译无错误;每台设备的
layout_verdict均为空;缩放比例等于canvas_scale或panel_scale;UIAudit错误和警告均为 0(包括排序平局、世界空间画布、静态遮罩、 居中锚定边缘和图集设置);TMP 和 UI Toolkit 的字形门槛均为缺失 0;保留 USS 规则;Play 和 Edit Mode 测试失败数为 0;静态面板为 1 个批次;空闲 HUD 的 GC 为 0, 面板变更数为 0。 - 视觉: 联系表和 4K 裁剪图;根据层级、调色板、对比度、间距、所有尺寸下形状一致,以及 HUD 在关卡画面上的可读性进行评判。
常见错误
| 错误 | 表现 | 修复方法 |
|---|---|---|
| 用摄像机捕获 Overlay UI | 帧画面中没有 UI | CaptureUGUI |
| 使用横屏参考图时将 Match 设为 0 | 纵向 UI 缩小到 0.56 倍 | 设为 Match 0.5,或每种屏幕方向使用一个画布 |
| 在 UI Toolkit 中使用相同的 Match 值 | 纵向 HUD 大 17% | panel_scale |
| 将自定义着色器用于 uGUI | 过时的 2022 年建议 | 用于 UI Toolkit 的 UI Shader Graph(6.3) |
| 两个层使用相同的排序顺序 | 暂停菜单显示在 HUD 下方,点击事件发给了错误的系统 | 使用一个表格,并设置不同的值 |
| 焦点留在另一个系统中 | 在 UI Toolkit 上方弹出 uGUI 后,游戏手柄失效 | 进入时调用 SetSelectedGameObject,返回时调用 element.Focus() |
| 角落 UI 使用居中锚点 | 在 21:9 屏幕上,计数器偏移到屏幕外 | 使用角落锚点 |
| 仅用 SetActive / Canvas.enabled 隐藏 | 重建时出现峰值 / 隐藏的按钮仍可导航 | MenuScreen.Show |
| 在 Control Child Size 下放置空子项 | 元素消失 | 设置 Layout Element 下限;使用 ExplainLayout |
| 每个敌人条都使用一个画布 | 批次数随敌人数量增加 | 共用画布、UI Toolkit 世界空间、精灵 |
圆角 overflow: hidden 或用于小地图的 Mask | 每个遮罩都会打断批处理 | 预先裁切边框图,使用着色器裁剪 |
| UI 图集启用旋转或紧密打包 | 图标上下颠倒或出现溢色 | 取消勾选这两个选项 |
| 预期 UI Toolkit 使用 TMP 回退字体 | HUD 中出现方框字 | Panel Text Settings 回退字体、UitkGlyphs |
| 下拉列表由代码填充 | 切换区域设置后仍显示英文 | 在区域设置事件中重新填充 |
仅使用类级别的 [GeneratePropertyBag] | 使用反射绑定 | 还需添加 [assembly: GeneratePropertyBagsForAssembly] |
| 对隐藏数分钟的屏幕使用 display none | 绑定开销仍在持续 | RemoveFromHierarchy |
| 出现一条 USS 错误 | 整个样式表被丢弃,UI 未设置样式 | ImportReport rules > 0 |
| 将 Frame Debugger 作为门槛 | Agent 无法读取任何内容 | 使用 Render/Batches Count 记录器 |
| 没有首次选择项;使用默认 UI 操作 | 键盘失效;重新绑定被忽略 | MenuScreen.FirstSelected;InputSystem.actions |
| 订阅后未取消订阅 | 重新加载时处理程序不断累积 | 在 OnDisable/OnDestroy 中注册、初始化,并使用 -= |
交接
- 接收来自 scenario-unity-architecture 的模型、事件和 Input actions 资源;来自
scenario-unity-gameplay 的 AudioMixer(公开了 MasterVol/MusicVol/SFXVol);来自
scenario-unity-rendering-lighting 的质量级别(运行时,
QualitySettings.names仅列出 平台的级别);来自美术人员、scenario-unity-2d 或 scenario-* 技能的精灵和图标 (已打图集,关闭旋转和紧密打包)。 - 交付给 scenario-unity-mobile:安全区域面板的每个系统一个根节点(UI Toolkit:
RuntimePanelUtils.ScreenToPanel,并翻转 y 轴);交付给 scenario-unity-performance: 计数器 CSV;交付给 scenario-unity-shaders:UI Shader Graph 或 Canvas 材质(小地图裁剪、 模糊);交付给 scenario-unity-pipeline-automation:UI 场景、用于 CI 的 Play 和 Edit Mode 测试。交付包:场景、带判定结果的捕获表、审计 JSON、测试总数、Verified 和 Assumed。
Unity 6.3 说明
- TextMeshPro 包含在
com.unity.ugui2.0 中;批处理模式下,TMP_PackageResourceImporter找不到包路径(UISetup.ImportTmpEssentials)。enableWordWrapping已弃用。 - 同时使用
UnityEngine.UI和UnityEngine.UIElements会导致Image、Button、Slider名称冲突(CS0104):请为它们设置别名。 - 运行时绑定从 6000.0 起提供;世界空间 UI Toolkit 从 6.2 起提供;6.3 新增 UI Shader
Graph、USS
filter、aspect-ratio、SVG、UI Test Framework 包 (com.unity.ui.test-framework6.3.0,内置),以及更严格的 USS 解析器:任何错误都会 导致样式表为空,并标记为importedWithErrors(实测)。PanelSettings.vertexBudget、textureSlotCount、SetPanelChangeReceiver均为公开成员。标记:Scripts/UIElements.UpdateRuntimeBindings、.UpdateLayout、.UpdateStyle。 EditorSceneManager.NewScene会卸载未被引用的资源:请先创建场景,再加载 UXML。- 6.3 之后:6.5 中,Panel Renderer 将取代 UIDocument(后者仍可继续使用),并新增 uGUI
Raycast Receiver;6.6 移除 UXML Factory/Traits(现在使用
[UxmlElement])。
参考资料
references/procedures.md:二十一个 Agent 操作流程,包含完整 调用、实时测试和记录结果。references/expert-notes.md:按专家整理的原则,附带时间戳; 经测量的声明已标注。references/critique.md:用于评估布局、外观、行为、结构和成本的标准。references/gui-paths.md:通过编辑器窗口和菜单执行相同工作的 方法。references/sources.md:所有来源,以及凭据、URL 和最佳时间戳。