包体膨胀是慢性病
游戏包体很少在一天内突然变大。更常见的是每个版本多一点:活动留下几张图,旧皮肤资源没删,测试音效忘了清,某个 UI 图集被首包引用,两个角色各带一份相同纹理。等发版前一看,包体已经涨了几百 MB。
资源引用审计的目标,是把这种慢性增长变成可见变化。它不是发版前的清理运动,而应该成为日常工具。每次新增资源、每次改依赖、每次打包,都能知道体积变化和影响范围。
先建立依赖图
资源审计离不开依赖图。Prefab、材质、纹理、动画、音频、字体、图集、配置动态引用,都应该尽量进入图里。静态引用可以由引擎工具扫描,动态引用则需要配置声明或约定目录。
flowchart TD
A[资源扫描器] --> B[静态引用图]
C[配置表/活动入口] --> D[动态引用声明]
B --> E[统一资源依赖图]
D --> E
E --> F[未使用资源报告]
E --> G[首包污染报告]
E --> H[跨模块引用报告]
E --> I[重复资源报告]
依赖图不必一开始完美,但要能持续改进。工具应该允许标注“运行时动态加载”“保留用于回滚”“平台专用”等原因,避免把正常资源误报成垃圾。
未使用不等于可删除
未使用资源报告最容易被误用。某个资源没有静态引用,可能确实该删,也可能由运营配置动态加载,或者用于旧版本回滚。删除前要看证据链:最后修改时间、所属模块、负责人、线上是否有动态引用、是否被历史 Manifest 使用。
比较安全的流程是先标记候选,下一轮构建或灰度中观察是否有加载缺失,再删除。对大资源可以先从首包移到按需包,而不是马上物理删除。资源治理要稳,不要为了省包体制造线上缺图。
跨模块引用会污染首包
一个活动按钮引用了大厅图集,或者大厅预制体引用了活动图集,都会导致包体边界变脏。首包污染常常不是因为资源本身大,而是因为一条不该有的引用把整个包拉进来。
审计报告要能回答“为什么这个资源进了首包”。从首包入口一路展开依赖,找到具体引用链。只有看到引用链,业务同学才知道该拆图集、改预制体,还是调整加载方式。
重复资源要有归并策略
重复贴图、重复音效、重复字体在多团队并行时很常见。工具可以按哈希找完全相同文件,也可以按尺寸、名称和相似度找疑似重复。但归并不能只靠工具自动做,因为不同模块可能有不同压缩格式、平台要求和美术归属。
比较现实的做法是先处理完全相同的大文件,再处理高价值疑似重复。归并后要保证引用更新、平台变体正确、资源所有权清楚。否则下次别人找不到公共资源,又会重新导入一份。
小结
资源引用审计把“包体怎么又大了”变成具体问题:谁新增了什么,为什么进入首包,依赖链在哪里,能否移动或删除。工具给证据,人做判断,流程持续运行,包体才不会靠发版前熬夜清理维持。
审计报告要让人愿意看
资源引用审计如果只输出几万行路径,没人会看。报告要按问题类型聚合:未使用资源、重复资源、过大资源、循环依赖、跨模块引用、首包污染、平台不匹配。每类问题给出数量、体积、负责人和建议动作,才有机会被处理。
审计还要区分“可删”和“需确认”。有些资源看似未引用,实际由运营配置或远端活动动态加载;有些资源被旧版本回滚依赖,不能马上删。工具不能自信地误删,应该给出证据链,让负责人判断。
真正有效的审计是持续发生的。每次合入资源都生成差异报告:新增了多少体积,污染了哪些包,是否引入跨模块依赖。这样团队不会到发版前一天才发现包体涨了 300MB。
动态资源要显式声明
资源审计最难的是动态加载。代码里拼路径、配置里写资源名、服务端下发皮肤 ID,这些都不容易被静态扫描发现。结果工具报告资源未使用,工程师删掉后,线上活动才发现缺图。
解决办法不是放弃审计,而是要求动态资源显式声明。活动配置声明会用到哪些图集和特效,皮肤配置声明模型、材质和动作,剧情配置声明语音和立绘。声明可以由工具从配置生成,但不能靠运行时猜。
对确实无法静态确定的资源,可以放入动态保留清单,并要求写明负责人、用途和过期时间。没有过期时间的保留清单会变成垃圾桶,最后所有可疑资源都被塞进去,审计失效。
首包污染要按引用链治理
发现首包变大后,很多团队第一反应是压缩资源。但如果根因是引用链错误,压缩只能缓解,不能解决。比如一个首包 UI 引用了通用角色展示组件,而这个组件默认引用全角色材质。真正要改的是组件边界:首包 UI 用轻量展示组件,需要角色详情时再按需加载。
引用链报告最好能排序:按体积贡献、按层级深度、按新增时间。体积贡献告诉你先处理哪个最划算,层级深度告诉你问题是否是间接依赖,新增时间帮助找到是哪次提交引入的。
治理时不要只看单个资源。一个 200KB 的 Prefab 可能拉入 80MB 纹理;一个小配置可能引用整个活动包。审计工具要按闭包体积计算影响,而不是只看自身文件大小。
重复资源背后常是流程问题
重复资源不是简单“谁导入错了”。可能是团队没有公共资源库,美术不知道已有资源;也可能是不同平台需要不同压缩格式,被误判为重复;还可能是版本分支并行开发,合并时两边都带了一份。
处理重复资源时,要顺手修流程。建立公共图标、通用音效、基础材质和字体库;导入工具提示相同哈希资源已存在;代码评审或资源评审看新增体积;大型活动结束后安排资源归档。否则删完一批,下个版本还会回来。
对相似但不完全相同的资源,要让美术参与判断。技术工具可以指出两个图标 95% 相似,但是否能合并取决于视觉标准、压缩质量和品牌要求。工程治理不是替代专业判断,而是把问题摆到桌面。
审计要进入 CI 或发版门禁
如果资源审计只是某个工程师偶尔跑一次,它很难长期有效。至少在发版前,审计报告应该成为门禁:首包体积超过阈值要解释,新增未声明动态资源要阻断,跨模块引用要确认,重复大资源要处理或登记豁免。
门禁也要允许合理豁免。比如春节版本确实需要增加首包资源,但要写清原因、体积、下线清理时间。没有豁免机制,团队会绕过工具;没有记录,临时增加会永久留下。
资源所有权要明确
审计报告如果没有负责人,很难推动处理。每个资源包、目录或模块应该有 owner。报告里显示“这个资源属于谁”,负责人才能判断删、移、压缩还是保留。没有 owner 的资源可以先归到待认领列表,长期无人认领的高体积资源重点清理。
所有权还包括生命周期。活动资源什么时候下线,联动资源是否有版权期限,旧赛季资源是否保留回放,测试资源是否只在开发包存在。资源如果没有生命周期,就会默认永久存在。
平台差异要纳入审计
Android、iOS、PC 或不同渠道可能使用不同纹理压缩和资源格式。审计时不能只看源文件大小,也要看各平台打包后体积。某张 PNG 源文件不大,转成某平台格式后可能膨胀;某段音频在一个平台压缩良好,在另一个平台却很大。
平台专用资源也要防串包。Android 专用视频不应进入 iOS 包,高清平板资源不应进入低端手机默认包。打包报告按平台输出,才能发现这些问题。
审计结果要进入复盘
每次版本结束后,可以复盘包体变化:哪些模块增长最多,哪些资源下线后已清理,哪些临时豁免还没处理,哪些工具规则误报或漏报。复盘不是追责,而是让下个版本少重复同样问题。
如果某类问题反复出现,比如活动图集总污染首包,就说明需要改模板或导入流程,而不是每次手工清理。资源治理的目标是减少问题产生,而不是提高打扫速度。
删除也要可回滚
删资源前要确认不会影响回滚版本和线上动态配置。对高风险删除,可以先在灰度包或内部包移除,监控资源加载失败。发布系统也可以保留删除清单,出问题时快速恢复。
删除后还要清理引用。残留配置指向已删资源,会在未来某次活动复用时爆雷。审计工具应在删除后继续扫描悬挂引用,把它们作为错误而不是警告。
从报告走向行动
资源审计最容易停在“发现很多问题”。真正有用的是把问题变成行动列表:本版本必须处理的阻断项,发版后清理的跟踪项,可以接受的豁免项,工具误报的改进项。每一项都有负责人和截止时间,审计才会影响结果。
也不要把审计做成只会报错的工具。它应该帮助团队理解资源结构:哪些模块最重,哪些资源复用最多,哪些活动下线后能释放空间。理解结构以后,包体优化才不会每次都从零开始。
把资源问题前移到导入时
最便宜的资源治理发生在导入那一刻。导入工具可以检查命名、尺寸、压缩格式、目标平台、所属模块和是否已有重复资源。发现问题时立刻提醒,比几周后在审计报告里追查容易得多。比如一张 4096 的 UI 图刚导入就提示超出规范,负责人还能马上找美术改;等它进入多个图集和资源包后,处理成本会高很多。
导入规则也要允许项目例外。Boss 宣传图可能确实很大,剧情视频可能有特殊格式。例外要登记,而不是让工具静默放过。
审计指标要长期看趋势
一次审计只能说明当前状态,趋势才能说明治理是否有效。可以每个版本记录首包体积、总资源体积、未使用候选体积、重复资源体积、跨模块引用数量和豁免数量。如果豁免越来越多,说明规则被绕过;如果未使用候选持续上升,说明下线清理没有跟上。
趋势图能让资源治理从“临时减肥”变成健康管理。团队不必每次都等包体报警,而是提前看到问题正在累积。
资源审计做得越早,争论越少。它让包体、依赖和清理责任都变成可见事实,而不是发版前的主观印象。
持续审计的意义,就是让这些事实在问题变大之前出现。
资源治理不是一次性清理,而是让新增、引用、下线和回滚都有据可查,团队以后才能少靠记忆维护包体。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。