# Unity UI 降 DC 优化包(可移植归档) > 归档时间:2026-09-10 | 来源工程:T5(`d:\Project\T5`)、T11(`d:\Project\T11`) > 一句话:**四条互相独立的降 DrawCall 路线 + 配套巡检工具 + 排查方法论,全部来自 T5/T11 实战并已验证生效,业务代码零改动。** --- ## 一、这个包解决什么问题 Unity UI 的 DrawCall 高,通常是四个不同原因叠加。本包按**功能**分成四个目录,可以单独取用,互不依赖: | 路线 | 病因 | 药方 | 目录 | | --- | --- | --- | --- | | **① UIEffect 材质共享** | Coffee.UIEffect 5.x 给每个组件建独立材质实例(缓存 key 用实例唯一的 `effectId`)→ 100 个同配置图标 = 100 个材质 = 完全无法合批 | 把缓存 key 换成**配置内容指纹 `configId`** → N 个同配置特效共享 1 个材质 → 可被 UGUI 动态合批 | `01_` | | **② 全屏面板遮挡** | 全屏界面打开时,被完全盖住的下层界面**照样提交 DC**(GPU 白画一遍) | 挂 `FullScreenCover` 组件 → 打开时把下层 `SetActive(false)`,关闭时自动恢复 | `02_` | | **③ 渲染设置与资源清理** | URP Renderer 里 SSAO 等 Feature 在 2D/UI 场景纯属浪费;超大散图撑包体 | 关掉 SSAO(省 4 个 DC)、Skybox 改纯色、删无用大图 | `03_` | | **④ 巡检工具** | 靠人眼在几百个 prefab 里找问题不现实 | Prefab/图片/图集静态扫描 + 界面性能巡检(含相似图 LSH、dHash) | `04_` | **T5 实测总收益**:大厅整帧批次数 **约 100 → 35**;等级礼包面板 **~101 → 30~40** 量级(①的贡献,具体取决于同面板内同配置特效数量)。 另外 `05_` 是排查方法论(Frame Debugger 看图、编辑器 FPS 乱跳、Profiler 三步法),`99_` 是原始提交全量 diff(仅供对照,**不建议直接 apply**,原因见第五章)。 --- ## 二、目录结构与文件清单 > ★ = 必读/推荐入口。每个功能目录内都是「补丁 + 成品源码 + 说明文档」三件套,可单独取用。 ``` DC优化归档/ ├── README.md ← 本文件(总入口) │ ├── 01_UIEffect材质共享降DC/ ← 路线①:同配置特效共享材质 │ ├── 移植与验证手册.md ★必读 8 章:前提核对/安装/验证/回滚/坑 │ ├── uieffect_configId.patch ★推荐 git 标准补丁(2 文件 +126 -2) │ ├── UIEffectContext.cs 打完补丁的成品源码(兜底覆盖用) │ ├── UIEffectBase.cs 打完补丁的成品源码(兜底覆盖用) │ └── UIEffect降DC改动总结.md T11 原始技术文档(方案选型 + 指纹算法) │ ├── 02_全屏面板遮挡省DC/ ← 路线②:盖住的界面不再出 DC │ ├── FullScreenCover_使用方法与避坑.md ★必读 9 章:配置/原理/移植/★2 个真实陷阱/排查 │ ├── fullscreen_cover_mechanism.patch ★推荐 git 标准补丁(4 文件 +474) │ ├── FullScreenCover.cs 组件本体(17 行,挂预制体根节点) │ ├── IPanelBase.cs 接口(新增 5 个成员) │ ├── PanelBase.cs 核心实现(遮挡/恢复全部逻辑) │ └── FullScreenCoverTool.cs 编辑器工具(Tools/UI/全屏面板遮挡工具) │ ├── 03_渲染设置与资源清理/ ← 路线③:渲染管线开销 │ └── urp_关闭SSAO.patch URP Renderer 的 SSAO m_Active 1→0(省 4 DC) │ ├── 04_性能与图片巡检工具/ ← 路线④:批量找问题 │ ├── UIPrefabCheck_能力与优化清单.md ★必读 7 个标签页能力表 + 4 个缺口 + 分级优化方案 │ └── UIPrefabCheck.cs 工具源码副本(1434 行,只读归档) │ ├── 05_排查方法论/ │ └── DC与帧率排查经验.md Frame Debugger 看图/编辑器 FPS 乱跳/Profiler 三步法 │ └── 99_原始提交备查/ ← 仅供对照,不建议直接 apply ├── T5_c61b9012_UIEffect补丁提交.patch 路线① 在 T5 的原始提交(混入了 prefab 改动) └── T5_cdbbca4b_DC战役总提交.patch 路线②③ 的总提交(905 KB,含删 30MB 大图) ``` ### 各路线的动手前必读 | 路线 | 必读文档 | 核心前提 | | --- | --- | --- | | ① UIEffect | `01_/移植与验证手册.md` | UIEffect 必须是**本地源码包**(`file:` 引用),不能是 PackageCache 只读包 | | ② 全屏遮挡 | `02_/FullScreenCover_使用方法与避坑.md` | 必须用 MFrame 的 `PanelBase` + `PanelMgr` + `UILayerIdx` 体系;**第七章两个陷阱务必看** | | ③ 渲染设置 | 无(补丁即说明) | URP;2D/UI 场景才有意义 | | ④ 巡检工具 | `04_/UIPrefabCheck_能力与优化清单.md` | 静态扫描 6 页删 `using MFrame;` 即可搬走;性能巡检页**强绑 T5 框架需重写** | --- ## 三、快速开始 四条路线**互相独立**,按需取用。建议顺序:③(改一个数字,风险最低)→ ② → ① → ④(工具,最后上)。 ### 路线③ 渲染设置(最简单,先看这个) ```powershell cd <目标工程 git 根目录> git apply --3way "<归档路径>\03_渲染设置与资源清理\urp_关闭SSAO.patch" ``` 只改一个 `m_Active: 1 → 0`。也可以在 Unity 里手动做:选中 URP Renderer 资产 → 找到 SSAO Feature → 取消勾选。2D/UI 场景关掉无视觉损失。 ### 路线② 全屏遮挡 ```powershell cd <目标工程 git 根目录> git apply --check "<归档路径>\02_全屏面板遮挡省DC\fullscreen_cover_mechanism.patch" git apply --3way "<归档路径>\02_全屏面板遮挡省DC\fullscreen_cover_mechanism.patch" ``` **动手前必须先读** `02_/FullScreenCover_使用方法与避坑.md` 第六章(前提核对)与**第七章(两个真实陷阱)**。编译通过后用菜单 `Tools/UI/全屏面板遮挡工具` 逐个挂组件,**一次只挂一个并立即验证**。 ### 路线① UIEffect(3 步) 前提:目标工程把 UIEffect 以**本地源码包**方式引入(`Packages/manifest.json` 里形如 `"com.coffee.ui-effect": "file:../my_libs/unityLib/UIEffect-main/Packages/src"`)。 如果它在 `Library/PackageCache/` 下(只读),先按手册第二章把它生成本地包,否则改了也白改。 ```powershell # 1) 进目标工程的 git 根目录(T5 是 <项目>/T5_game) cd <目标工程 git 根目录> # 2) 应用补丁(--3way 允许三方合并,冲突时会在文件里留标记) git apply --3way "<归档路径>\01_UIEffect材质共享降DC\uieffect_configId.patch" # 3) 回 Unity 编译,打开目标面板用 Frame Debugger 看批次是否下降 ``` apply 失败(版本不同、路径不同)就走兜底:把 `01_UIEffect材质共享降DC/` 里的两个 `.cs` 直接覆盖到目标工程的 `.../UIEffect-main/Packages/src/Runtime/` 下;再不行就照 `移植与验证手册.md` 第三章手工贴代码块。 ### 路线④ 巡检工具 把 `04_/UIPrefabCheck.cs` 拷到目标工程 `Assets/Editor/` 下即可。静态扫描 6 页可能需删 `using MFrame;`;性能巡检页强绑 T5 框架,详见 `UIPrefabCheck_能力与优化清单.md` 第五章。 --- ## 四、路线① 改动核心(速览) **`UIEffectBase.cs` → `GetModifiedMaterial()`**,材质缓存 key 换掉: ```csharp // 改前:effectId = 组件实例唯一 → 永不共享 var rootId = (uint)(transitionRoot != null ? transitionRoot.GetHashCode() : 0); var hash = new Hash128((uint)baseMaterial.GetHashCode(), effectId, samplingScaleId, rootId); // 改后:configId = 配置内容指纹 → 同配置共享 var configId = context.configId; var rootId = context.useViewMatrix && transitionRoot ? (uint)transitionRoot.GetInstanceID() : 0u; var hash = new Hash128((uint)baseMaterial.GetInstanceID(), configId, samplingScaleId, rootId); ``` **`UIEffectContext.cs`**,新增 121 行:`configId` 属性(反射遍历所有 public 序列化字段 → FNV-1a 混合 → MurmurHash3 终混雪崩),配套 `Mix` / `HashValue` / `HashFields` / `GradientHash` 与两个静态缓存 `s_ConfigFields`、`s_FieldCache`。 三个设计要点(细节见 `UIEffect降DC改动总结.md`): 1. **反射结果静态缓存**:`GetFields` 只在类型加载时跑一次,运行时无类型发现开销,避免批量刷新时的 GC 尖峰; 2. **`Gradient` 按内容哈希**:不同实例、内容相同的渐变得到相同指纹(否则按引用哈希会白拆批次); 3. **`rootId` 仅在需要视图矩阵时参与**(transition / gradation / detail / shiny),普通灰度不受 root 影响,**共享范围更大**。 --- ## 五、来源与可追溯性 | 项目 | 提交 | 路线 | 说明 | | --- | --- | --- | --- | | T11 | `fa5f0cdb 降低DC的操作`(2026-08-26) | ① | 首次实现,产出 `UIEffect降DC改动总结.md` | | T5 | `cdbbca4b 提交DC优化` | ②③ | FullScreenCover 整套机制 + 关 SSAO + 删 30MB 无用大图 | | T5 | `c61b9012 优化DC`(2026-09-08) | ① | 从 T11 移植到 T5,验证生效(DC 确认下降) | | T5 | `d9fc47e0 debug` | ② | 因副本异常把 `UI_RaidSelectPanel` 的 FullScreenCover **摘掉**(详见 02_ 文档第七章) | > **为何 `99_原始提交备查/` 里的补丁不建议直接 apply**:两个提交都是“搭车提交”,路线混在一起: > - `c61b9012` 除了路线① 的 2 个源码文件,还捎带了 7 个面板 prefab 的 `isKeepShowWhenCovered: 1 → 0`(属路线②的配置); > - `cdbbca4b` 除了路线②③,还含删图、prefab 改动等共 905 KB diff。 > > 所以各功能目录里提供的是**拆分后的纯净补丁**(`uieffect_configId.patch`、`fullscreen_cover_mechanism.patch`、`urp_关闭SSAO.patch`), > 原始提交只用于事后对照“T5 当时到底改了什么”。 --- ## 六、本包缺什么(诚实说明) - **⚠ 路线② 有一个已知隐患未修,随包一起交付**:`PanelBase.RestorePanelsHiddenByMe()` 只看“是否被遮挡隐藏”, 不看“是否已被业务 Close”,导致已关闭的面板可能被 `SetActive(true)` 复活。T5 副本异常就是这么来的, 当时的处置是**把 RaidSelectPanel 的组件摘掉**(保守做法),**框架层的 4 行守卫至今未实施**(已核实:PanelBase 全文搜 `_closed`/`isClosed` 零命中)。 归档的源码是 T5 当前真实状态(含隐患),修复代码已写在 `02_/FullScreenCover_使用方法与避坑.md` 第七章陷阱一,移植时建议一并补上。 - **UI DC 体检工具(`UIDCProbeTool.cs`)没有归档进来**:该工具在 T5 里按需求删除时**从未提交进 git**, 会话缓存中也没有源码副本,已不可恢复。它当时的能力是:运行时按 Canvas 采集真实批次 + 材质分组模式 (按材质/纹理 hash 归组,定位"谁在拆批次")。如果新项目需要,可按 `05_/DC与帧率排查经验.md` 的思路重建, 或直接用 Unity 自带的 Frame Debugger(多数场景够用)。 **更推荐的替代路线**:`04_/UIPrefabCheck_能力与优化清单.md` 的 A1 + A2 两项——给界面性能巡检加 DC/批次指标、再给静态扫描加一页"合批体检",即可覆盖 UIDCProbeTool 的核心价值,而且静态分析可批量、 可导表、不需要 Play Mode,比原来那个运行时版本更好用。 - **`ShaderVariantRegistry.cs` 的 Profiler.EndSample 配对修复没有归档**:T11 文档提到过这个改动, 但 T5 当前插件版本(5.11.3)里该文件的采样配对本身已是正确的,未做修改,因此无补丁可归档。 若目标工程控制台出现 `Non-matching Profiler.EndSample`,按 `01_/移植与验证手册.md` 第四章处理。 - **路线③ 只归档了 SSAO 一项**:当时还做了 Skybox 改纯色、删三张超大图(map.png 30MB / bg.png ×2 各 ~2.5MB), 这些属于具体工程的美术决策,不具可移植性,只在 `99_/T5_cdbbca4b` 里能看到完整 diff。