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

12 KiB
Raw Blame History

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 → 3040 量级(①的贡献,具体取决于同面板内同配置特效数量)。

另外 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 框架需重写

三、快速开始

四条路线互相独立,按需取用。建议顺序:③(改一个数字,风险最低)→ ② → ① → ④(工具,最后上)。

路线③ 渲染设置(最简单,先看这个)

cd <目标工程 git 根目录>
git apply --3way "<归档路径>\03_渲染设置与资源清理\urp_关闭SSAO.patch"

只改一个 m_Active: 1 → 0。也可以在 Unity 里手动做:选中 URP Renderer 资产 → 找到 SSAO Feature → 取消勾选。2D/UI 场景关掉无视觉损失。

路线② 全屏遮挡

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/ 下(只读),先按手册第二章把它生成本地包,否则改了也白改。

# 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 换掉:

// 改前: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。