☰
Unity项目膨胀元凶:Library/Artifacts缓存清理与Shader变体治理实战
2026/9/28 5:53:17 网站建设 项目流程

做Unity项目最怕的不是代码写不出,而是某天打开磁盘一看,整个项目文件夹直接吹成三四十个GB。我第一次遇到这种情况的时候,盯着硬盘里的目录愣了半天:项目源码加上美术资源总共也就五六个GB,哪来这么大的体积?点开属性一看,好家伙,Library/Artifacts一个文件夹就占掉了二十多GB。这个文件夹在Unity 2019.3启用Asset Pipeline v2之后变得尤其常见,很多项目里它能长到比整个工程本身还大好几倍。这篇内容不会绕弯子,直接讲清楚它到底从哪来、为什么这么肥、以及怎么在不破坏工程的前提下把它安全瘦下去。不论你是个人开发者,还是带着团队做项目,这套排查和治理思路都适用。

1. Artifacts文件夹到底是个什么东西

1.1 它藏在项目的哪个角落

按默认布局,Unity项目根目录下除了Assets、ProjectSettings、Packages这些大家熟悉的目录之外,还有一个经常被忽略的Library目录。Artifacts就在这个Library目录下面,路径通常是项目根目录/Library/Artifacts。另外,有些Unity版本在构建过程中也会在项目根目录生成一个Artifacts文件夹,存放打包流程的中间产物,比如AssetBundle构建时的临时文件、增量构建的映射数据等。绝大多数情况下,你看到的体量异常的那个是Library/Artifacts。

这个目录是按哈希值组织的一层层子目录,初看根本不知道里面是什么。外层的目录名是一串十六进制字符,里面的文件名也基本是GUID形式,不像Assets目录里那样有语义化的文件名。很多美术同学第一次打开这个目录会以为是电脑系统文件,其实它就是Unity自己管理的“内部仓库”。这个仓库里的东西项目运行时不直接读取,但导入资源、生成Shader变体、检查资源依赖关系时全都靠它。

1.2 里面都放了些什么东西

Artifacts里存放的是资源导入管线执行完之后的中间产物。Unity拿到一张PSD、一个FBX、一段音频,不可能每次用到都重新解算一遍原始文件,所以导入时会把处理好的中间结果写进这个目录,下次加载直接读结果。这里面主要包括:

  • 纹理的压缩中间格式和Mipmap数据
  • 音频的预解码缓存
  • Shader的编译结果和变体集合
  • 材质、动画等资源的序列化中间数据
  • 脚本编译过程中产生的程序集副本
  • AssetBundle构建的临时映射

也就是说,Artifacts的内容和你的资源体量强相关。你每新增一张贴图、一个材质球、一段动画、一个Shader变体,对应都会在这个目录里写入一份中间数据。正常情况下一两个GB可以接受,但是如果管理不当,它会在不知不觉中膨胀到完全超出你的预期。

1.3 一个比喻:它像项目的备料冷藏库

你可以把整个Unity项目想象成一家餐厅。Assets目录是货架上的生鲜食材,ProjectSettings是菜谱和规章制度,而Library/Artifacts就是后厨的冷藏库。厨师做菜之前会把食材切好、焯好、腌制好,放进冷库备用,出菜的时候直接取用,客人就不用等。这个冷库很实用,但它也会越堆越满:切多了一堆土豆丝、腌多了一堆鸡翅,如果从来没人清理,冷库最终会被废料和过期食材塞满。Unity的Artifacts差不多就是这么回事——它帮我们节省日常打开项目的时间,但如果你不主动管理,它就是这个项目里最容易“积灰”的地方。

2. 为什么Artifacts会膨胀到失控

2.1 Shader变体是最大的“肥胖源”

很多项目点开Artifacts一看,体积最大的往往是和Shader相关的缓存数据。Shader的变体膨胀发生在你加了Shader关键字(keyword)之后。每个关键字在材质上都有“开”和“关”两种状态,一旦你用multi_compile声明了若干个关键字,变体数就会按组合数增长:10个关键字的理论组合数是1024种,每个变体又需要单独编译一份Shader代码。假设你的场景里有100个材质球,它们又不小心各自开启了不同的关键字组合,Shader编译缓存瞬间就能给你堆出几个GB的中间文件。

这还没算多Pass的情况。Shader里写了多个Pass,每一个Pass都会把变体组合再翻一遍。更麻烦的是,现在的很多美术效果会用ShaderGraph去做,ShaderGraph生成出来的Shader默认会带上一大批Multi_compile关键字,比如雾效、光照贴图、阴影、方向光等相关的关键字。你根本没写几行代码,但导入时Unity会按照默认规则把所有可能的变体都编译一份缓存起来。这块数据长起来的速度,比你贴图资源涨得还快。

2.2 平台切换带来的历史包袱

Unity的资源导入和Shader编译结果都是分平台独立缓存的。同一个项目,在Windows编辑器以DX11渲染平台运行,Shader会按DX11变体编译一份;切换到Android平台,Unity又会按OpenGL ES或Vulkan再编译一份;再切到iOS,又会来一轮。理论上Unity的导入管线会清理当前不用的平台数据,但实际用下来你会发现,Library/Artifacts里留下了大量切换平台前的老数据。

打个比方,你今天在Windows上开发,明天接了个真机调试任务切到Android,后天又有人让你看看iOS的兼容性。每次切换平台,Unity都要额外生成当前平台的Shader变体,但旧平台的数据并不会老老实实删光,而是被留在磁盘上堆着。到了后期,Artifacts里甚至可能同时躺着三四个平台的中间产物,看着就很吓人。

2.3 版本库误提交是团队项目的隐形炸弹

个人项目遇到Artifacts膨胀,基本是自己硬盘的问题,清理完就收工。但团队项目遇到这问题,经常还叠加另一个麻烦:有人不小心把Library目录提交到了Git仓库里。Unity的官方.gitignore模板里面明确把[Ll]ibrary/排掉了,但总有那么一次归档打包、一次强行git add -f、或者某个新同事没配忽略规则,把整个Library推进了版本库。从那以后,仓库里就永远躺着一个巨型历史包。

之后所有人git clone下来,都得把这个体积庞大的Library一起拉下来。更麻烦的是,每个人的Unity版本、平台设置不完全一致,这些已经入库的Artifacts对团队里大多数人来说是废数据,白占空间不说,还容易在资源版本冲突时造成一堆莫名其妙的“文件已修改”提示。我见过有团队因为这个直接把仓库堆积到80多GB的,分支一多,客户端直接拉不动。

2.4 还有一种不太起眼的情况:超大贴图和模型

说完Shader和版本管理,还得提一类不那么技术化但同样常见的情况:美术资源本身就特别大。很多项目习惯性导入4K甚至8K的TGA/PSD,又舍不得关掉“Read/Write Enabled”,或者把模型上的法线、切线、动画曲线全部原样保留。这些资源的原始体积摆在那里,导入后生成的中间格式只会更大。如果你项目里塞了几百个这种大文件又不做压缩处理,Artifacts的体积压根不需要什么“异常原因”,它就是单纯的庞大。

3. 亲手清一次Artifacts:方案与实操步骤

3.1 方案A:整删Library目录,一步到位

如果你只是想立刻把磁盘空间收复回来,最直接的做法是关闭Unity编辑器,然后整个删除Library目录。Unity把大部分可能出问题的导入状态都放在这个目录里,删掉以后,重开项目时会触发一次全量重新导入,所有资源会被重新处理一遍。这样Artifacts里面残留的历史缓存、错误中间文件、陈旧的Shader编译数据,全部都一次性消失。

具体步骤是这么做的:

  1. 彻底退出Unity编辑器。注意别只关窗口,确认后台没有Unity进程残留,Windows下可以在任务管理器里看,macOS下可以用活动监视器确认。
  2. 再确认一遍你的项目有版本控制。至少确认远端有一个稳定可回退的提交,这一步永远不要省。
  3. 删除项目根目录/Library,Windows下直接右键删除,macOS下直接拖废纸篓。
  4. 重新用Unity Hub打开项目,等待资源导入完成。

我实测过几个项目,这种方案一般能把十多个GB的Library清理到三五个GB。代价是重开项目要等一段时间,资源越多越久,常见体量的项目大概是20到40分钟,期间你会看着进度条发呆。如果项目很大且团队人多,建议安排在中午休息或者下班前操作,免得耽误联调。

3.2 方案B:只删Artifacts子目录,保住其他缓存

有些时候你不想把整个Library推倒重来。原因可能是你项目很大,全量重导入的成本太高,或者你只是想把磁盘上最占空间的那块瘦下来,其他编译缓存和历史索引还想留住。这时候可以只删除Library/Artifacts子目录,保留Library下的其他目录。

删除之前先看一下体量,macOS或Linux下可以用这样的命令定位:

# 查看Artifacts的占用情况 du -sh "/你的项目路径/Library/Artifacts" # 查看Library下各个子目录的体积 du -sh "/你的项目路径/Library/"*

Windows下直接右键文件夹看属性也行,或者用TreeSize、WizTree这类工具扫一下目录。确认Artifacts就是大头之后,关掉Unity,删除Library/Artifacts,再重新打开项目。Unity会自动重新生成一份新的Artifacts目录。

按我自己的经验,只删Artifacts和整删Library的重新导入时间差不多,因为资源导入过程中绝大多数时间和最终写入都在Artifacts里完成。但这个方案的好处是保留了ScriptAssemblies等编译缓存,脚本方面的增量重建会快很多。如果项目脚本数量庞大,你会感觉到差别。

3.3 方案C:用Unity Accelerator减轻本地缓存压力

如果你发现Artifacts的问题是长期性的,删了还会再长回来,那么考虑引入Unity Accelerator。这个工具相当于一个局域网内的“资源导入缓存服务”。原理是这样的:团队里有人导入过一份FBX或Shader数据之后,结果会缓存在Accelerator上;另一个人导入相同资源时,Unity会先从缓存服务器拉取结果,而不是在本地重新计算一遍。

这样做有两个直接收益:一是大家的本地Artifacts增长速度大幅度放慢,因为很多导入结果直接从远端拿来了;二是不同开发者的本地缓存内容一致,能少很多“你那里怎么没这个问题”的扯皮。配置方法不复杂,下载Unity Accelerator并启动后,在Unity菜单栏打开Edit/Preferences/Cache Server,填入服务器地址和端口,默认端口是10080。唯一需要注意的是,Accelerator自身也需要磁盘空间来存缓存,生产上要求不高的项目给它分个一两百GB的空间,很够用了。

3.4 给Git仓库配上忽略规则,防止二次膨胀

清理完本地,紧接着要做的一步就是确认版本控制规则是安全的。Unity官方维护了一套.gitignore,核心内容是这样的:

# Unity generated [Ll]ibrary/ [Tt]emp/ [Oo]bj/ [Bb]uild/ [Bb]uilds/ [Ll]ogs/ [Uu]serSettings/

我建议团队里每个人都在项目根目录放一份,并且做一个严格约定:任何情况下都不往版本库里提交Library。如果仓库里已经误提交了,需要用git rm -r --cached Library把目录从索引里挪出去,然后提交一次让仓库瘦下来。历史提交里还留着的大对象,用git filter-repo这类工具清理历史,但那个操作要非常小心,建议先全量备份远程仓库再做。

4. 从源头控制体积增长的长期手段

4.1 Shader变体专项治理

清理一次只是治标,如果Shader变体还在肆无忌惮地生成,用不了俩月Artifacts又会涨回来。所以更关键的是从管线层面做变体治理。

先说最基础的事项:区分multi_compile和shader_feature的使用场景。multi_compile生成的所有变体都会被无脑打进构建产物里,shader_feature则只在材质实际使用时才会保留对应变体。很多默认Shader模板里的关键字并不需要全部开启,你在材质里根本没用到的时候,用shader_feature就能让它们不进入构建。不过要注意运行时如果开启了某个没有收集进变体集的keyword,材质可能会出现粉红色错误,这就是过度剥离的代价,所以改完一定要用真实设备或者编辑器预览跑一遍。

其次,项目里应该显式维护一份ShaderVariantCollection(简称SVC),把运行时真正用到的变体收集起来,在构建设置里引用这份集合。尤其是战斗类动作游戏里,几十个技能特效可能会导致ShaderGraph生成几千个变体,但实际同时渲染的也就其中一部分。通过SVC可以把构建和导入阶段的变体总量控制在合理范围。

再进一步,Unity 2021.2之后的版本里,Build Settings提供了更多变体剥离选项,构建时可以按图形API或渲染特性自动剔除无关变体。建议团队开一次专项会议,梳理一遍Shader关键字的数量。很多时候一个Shader里写着写着就攒了十几个keyword,每个效果开关都希望保留,最后变体组合数成了一个天文数字。用枚举类型或者设置选项来收敛组合数,是长期最有效的手段。

4.2 资源导入参数调优

Artifacts的膨胀本质上是导入管线的中间结果膨胀,所以资源导入参数的设置也会直接影响它。我做资源规范的时候,要求团队重点检查这几项:

  • 纹理资源:关掉“Read/Write Enabled”,除非运行时需要反复修改像素数据;压缩格式根据目标平台选择,移动端优先ASTC,桌面端用BC系列;不生成Mipmap的就不用开,透明贴图这类如果用不到Mipmap也用默认值即可。
  • 模型资源:关掉不必要的“Read/Write”;Mesh Compression调到High,正常显示不会受明显影响;如果不需要动画,就把导入动画类型设为None,避免骨骼和曲线数据留在中间文件里。
  • 音频资源:长音频用压缩格式,短音效用Decompress On Load要谨慎。不要全项目一股脑全用Uncompressed。

这些设置不一定让单个文件小多少,但是积少成多。一个项目几千个资源,每张贴图少几MB中间数据,总体就能差出好几个GB。而且这些设置不只是省磁盘,对最终包体、加载内存都有正向影响,属于一举多得的优化。

4.3 团队协作与规范化管理

如果你的项目有多位开发者在不同电脑上工作,Artifacts的体量差异会非常明显。有人每天切平台,有人常年不删Library,有的电脑上还挂着好几个Unity版本的缓存。想让这种情况可控,团队在项目早期就应该立好规矩。

我推荐的做法有这几个:第一,官方.gitignore必须随项目仓库存在,新同事入职第一天就检查他的Git配置。第二,大体积美术资源不要直接塞进Assets目录后强制所有人拉取,考虑使用Git LFS或者独立的资源服务器,否则仓库体积和本地导入压力都会被拉爆。第三,维护一份内部文档,写明Artifacts目录的作用和清理流程,避免有人哪天手误把整个项目目录一股脑推上去了。

如果有条件,把导出资源的规范和Shader变体收集规则也写进去。Artifacts膨胀虽然看起来像技术问题,但本质上是一个工程管理问题。技术手段能帮你清一次、两次、三次,但只有规范流程才能让它不再周而复始地出现。

5. 真实案例复盘与常见问题排查

5.1 我处理过的一次“20GB Artifacts”案例

有一次接手一个做了半年的Unity项目,源码和美术资源加起来一共4.5GB,但项目的Library目录有19GB。我用WizTree扫了一遍,其中Artifacts占16GB左右,剩下的是Shader编译缓存和脚本程序集。排查过程分成三步。

第一步是定位体积大头。进入Library/Artifacts按目录大小排序,发现最大的一部分是Shader相关缓存,其次是纹理和模型导入的中间数据。第二步是查Editor日志,日志路径在Windows下是C:/Users/你的用户名/AppData/Local/Unity/Editor/Editor.log,macOS下是~/Library/Logs/Unity/Editor.log。日志里能看到最近几次导入和构建的记录,我发现团队过去三个月频繁切换Android和Windows平台,每次切平台都重新编译了一大批Shader变体,而旧数据一条都没清掉。第三步是看版本库,用git log --oneline -- Library查了一下,果然有几次提交不小心把Library目录一起打了进去。

处理流程就是先删掉本地Library/Artifacts目录,重新打开工程,等Unity完成一次全量导入。之后把仓库里的Library目录从索引移除,提交一次让仓库文件体积降下来。最后给团队的.gitignore补上严格规则,同时在开发机上装好Unity Accelerator。一个多月以后我再去看,那台开发机的Library稳定在6GB左右,没有反弹回十几GB的情况。

5.2 问题速查表:典型状况与解决办法

最后整理一个速查表,方便大家遇到类似问题的时候快速对号入座。

症状可能的原因处理方式
Artifacts占用十多个GB,且堆满Shader相关文件Shader变体数量膨胀、multi_compile关键字过多治理Shader关键字、收集ShaderVariantCollection
删除Artifacts后重开项目,导入等待时间很长正常现象,资源数量越多导入越慢加入Unity Accelerator,或安排在非工作时间操作
无人工操作,磁盘体积隔几天自动暴涨有资源被反复修改触发重导入,或编辑器未关闭时有自动构建任务查Editor.log定位触发者,完善增量导入流程
团队不同人的项目体积差异巨大每人切换平台、导入次数不同统一平台使用策略,启动Accelerator缓存
Git仓库越来越大,甚至卡顿Library/Artifacts被误提交用git rm -r --cached Library移除索引,必要时清理历史
删完Artifacts后某些材质变成粉红色Shader变体被过度剥离,或关键字未收集进SVC检查ShaderVariantCollection,补齐实际用到的变体
删除时提示文件被占用,删不掉Unity进程未完全退出,或杀毒软件锁文件强制退出Unity,关闭杀毒软件监控后重试
项目重新导入时报错,提示资源导入失败Artifacts中缓存损坏或索引残留删除该资源对应的Artifacts子目录,必要时整删Library

如果你不常折腾这类问题,我最后再给你一个实际建议:不要在Unity还开着的时候直接删Artifacts,也不要以为删除后项目会损坏。只要版本控制在手,删掉它真的不是高危操作,Unity会自动重建。真正需要警惕的是那些“看不见的源头”,比如Shader变体、平台切换遗留、版本库误提交。把这些源头管住了,Artifacts这个文件夹,就只是一个普通得不能再普通的缓存目录。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询