Files
Planner_Tools/Unity/DC优化/README.md
T
2026-09-10 17:29:24 +08:00

182 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<V>` + `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。