
1. 项目概述如果你在Unity项目开发中经历过项目体积随着版本迭代像吹气球一样膨胀或者打包时发现构建包里有大量你确信已经不再使用的材质、贴图、预制体那么你肯定对“项目清理”这件事又爱又恨。手动排查耗时耗力还容易误删。Unity自带的工具功能有限难以应对复杂的引用关系尤其是像Addressables这样的现代资源管理系统。这正是Unity-Dependencies-Hunter以下简称Dependencies Hunter诞生的背景。它是一款专门用于在Unity项目中查找和清理未引用资产的工具核心目标就是帮你精准定位那些“僵尸资产”从而优化项目结构、减小构建体积、提升团队协作效率。简单来说Dependencies Hunter就像一个专业的“项目资产审计员”。它不生产内容只做资产的搬运工和清算师。通过深度扫描项目内所有资产的依赖关系图它能告诉你哪些文件是真正被场景、脚本、或其他资产引用的哪些是孤零零躺在文件夹里吃灰的。对于任何规模超过原型的Unity项目无论是手游、PC游戏还是VR应用定期使用这类工具进行资产清理都是一项至关重要的性能优化和工程管理实践。接下来我将结合自己多次使用Dependencies Hunter的经验深入解析其工作原理、详细操作步骤并重点分享那些官方文档里不会写的“坑”和解决方案。2. 核心原理与工作流程拆解理解Dependencies Hunter如何工作是避免误操作和正确解读结果的关键。它的核心逻辑并不复杂但细节决定成败。2.1 依赖关系图的构建工具启动后首先会调用AssetDatabase.GetAllAssetPaths()获取项目Assets目录下所有资产的完整路径列表。这构成了扫描的“全集”。接着对于这个列表中的每一个资产工具会调用AssetDatabase.GetDependencies(string assetPath, bool recursive)方法。这个方法返回的是指定资产所直接或间接依赖的所有其他资产的路径列表。这里有一个关键点AssetDatabase.GetDependencies反映的是Unity序列化系统能识别到的引用。这包括序列化字段引用如public GameObject prefab;在Inspector中拖拽的引用。资源内嵌引用如Material中引用的TexturePrefab中引用的Mesh和Material。ScriptableObject中的数据引用。通过遍历所有资产并收集它们的依赖工具就在内存中构建了一张巨大的、有向的“资产依赖关系图”。在这个图中每个资产是一个节点如果资产A依赖于资产B就有一条从A指向B的边。2.2 “未引用”资产的判定构建好依赖图后判定“未引用”资产的逻辑就变得直观了在图中没有任何其他节点的边指向它的节点就是未被引用的资产。更技术化的说法是入度In-Degree为0的节点。但是这个“入度为0”需要经过几层过滤忽略特定路径用户可以通过正则表达式RegExp设置忽略模式比如忽略所有Editor/、Plugins/、Resources/文件夹下的资产。这些文件夹通常包含运行时不会打包的编辑器脚本、第三方库或需要动态加载的资源。Addressables检测如果开启了“Detect Addressables”选项工具会额外检查资产是否在Addressables资源组中注册。已注册的Addressables资产会被视为“已引用”即使它们在传统的依赖图中没有入边。因为Addressables系统会在运行时通过标签或地址来加载它们这是一种动态引用静态分析无法捕获。AssetReference扫描这是一个增强选项。默认情况下AssetDatabase.GetDependencies无法识别序列化为AssetReference类型的字段。开启“ScanForAssetReferences”后工具会以文本方式解析资产文件如.prefab, .asset查找AssetReference的GUID从而将这些引用加入依赖图。这会使扫描速度变慢但引用关系更完整。注意工具无法检测“字符串路径引用”或“运行时动态加载”。例如通过Resources.Load(“路径/资源名”)或AssetBundle.LoadAsset加载的资源在编辑器的静态分析中是完全不可见的。这类资源如果存放在Resources文件夹或被打进AssetBundle需要你手动将其添加到忽略列表或者依靠Addressables检测来“保护”它们。3. 安装与基础配置详解工欲善其事必先利其器。正确的安装和初始配置能避免很多后续麻烦。3.1 两种安装方式的选择与实操方式一通过UPMUnity Package Manager安装推荐这是最干净、最便于管理的方式尤其适合团队项目。在Unity编辑器中打开Window Package Manager。点击左上角的“”按钮选择“Add package from git URL...”。在弹出的输入框中粘贴Dependencies Hunter的Git仓库地址https://github.com/AlexeyPerov/Unity-Dependencies-Hunter.git。点击Add。Unity会自动下载并导入该包到项目的Packages目录下。优点非项目资产不污染Assets目录易于更新只需在Package Manager中更新依赖关系清晰。缺点需要网络连接对于内网开发环境可能不便。方式二直接复制C#脚本传统方式访问项目的GitHub页面找到根目录下的DependenciesHunter.cs文件。点击Raw按钮查看原始文件复制全部代码。在你的Unity项目的Assets目录下创建一个名为Editor的文件夹如果不存在。在Editor文件夹内创建一个新的C#脚本命名为DependenciesHunter.cs将复制的代码粘贴进去。优点离线可用直接嵌入项目无需管理包。缺点代码成为项目资产更新麻烦如果项目中有多个版本容易冲突。实操心得对于长期项目我强烈推荐使用UPM方式。它不仅管理方便更重要的是当工具更新时你可以清晰地看到版本变化。而直接复制脚本的方式可能在Unity编辑器版本升级后因为API变化而导致脚本编译报错你需要自己手动查找修复比较折腾。3.2 首次运行与窗口布局解析安装完成后通过菜单栏Tools Dependencies Hunter即可打开主窗口。这个窗口是工具的核心交互界面布局清晰但功能密集。窗口主要分为以下几个区域顶部控制区包含“Analyze Project”分析项目按钮和“Analysis Settings”分析设置折叠菜单。这是操作的起点。结果列表区分析完成后这里会以表格形式展示资产。默认只显示“Unreferenced Assets”未引用资产。每一列包括资产名、路径、类型、大小、引用数。你可以点击列标题进行排序例如按“Size”排序能快速找到占用空间最大的“僵尸资产”。底部操作区提供“Select All”全选、“Delete Selected”删除选中项等批量操作按钮以及显示选中资产总大小和总数的统计信息。首次打开时建议先不要急着点击“Analyze”而是点开“Analysis Settings”进行一番配置这能节省大量后续筛选时间。3.3 关键配置项忽略模式Ignore Patterns这是最重要的配置没有之一。合理的忽略模式能让你聚焦于真正需要清理的资产避免误报干扰。忽略模式使用正则表达式RegExp来匹配资产路径。工具内置了一些默认模式但你需要根据自己项目的结构进行定制。如何设置在“Analysis Settings”中找到“Ignore Patterns”列表。你可以直接在此添加、编辑或删除正则表达式。更推荐的做法是点击“Create Ignore Patterns Asset”按钮这会在Assets/Editor/下创建一个名为DependenciesHunterIgnorePatterns.asset的设置文件。这样做的好处是配置可以随项目版本管理团队共享。常用正则表达式示例.*/Editor/.*忽略所有Editor文件夹下的内容。编辑器脚本、扩展工具等不应被打包。.*/Plugins/.*忽略Plugins文件夹。通常存放原生插件.dll, .so, .bundle。.*\.asmdef$忽略所有程序集定义文件。这些是代码组织文件非资源。.*/Resources/.*谨慎使用Resources文件夹内的资源虽然可能未被直接引用但可以通过Resources.Load动态加载。如果你确定某些Resources下的资源确实无用可以不忽略如果不确定最好忽略或者清理前仔细审查。.*/StreamingAssets/.*忽略StreamingAssets文件夹。这里的文件会原样复制到构建包供运行时读取。.*/TextMesh Pro/.*如果你使用了TextMesh Pro其资源包内的字体、材质等通常不应被清理。.*\.cs$忽略所有C#脚本文件。避坑指南正则表达式中的.匹配任意字符*表示前一个字符出现0次或多次.*组合起来就是匹配任意长度的任意字符串。$表示字符串结尾。添加模式后建议先进行一次快速扫描观察结果列表是否如预期般过滤了相关路径。这是一个迭代调整的过程。4. 深度扫描Addressables与AssetReference处理现代Unity项目大量使用Addressables系统进行资源热更和内存管理这使得传统的依赖分析面临挑战。Dependencies Hunter对此提供了专门的支持但需要正确理解和使用。4.1 启用Addressables检测在“Analysis Settings”中勾选“Detect Addressables”选项。这个选项做了什么勾选后工具在分析时会额外读取项目的Addressables配置通常位于Assets/AddressableAssetsData下。任何在Addressables组中注册了的资产即使它在AssetDatabase的依赖图中没有被任何其他资产引用也会被工具标记为“已引用”从而不会出现在“未引用资产”的结果列表中。为什么需要这个选项Addressables的本质是“动态引用”。一个预制体可能没有被任何场景或资源直接引用但它被添加到了名为“UI”的Addressables组并设置了“UI_Popup”的地址。游戏运行时代码通过Addressables.LoadAssetAsyncGameObject(“UI_Popup”)来加载它。对于静态分析工具来说这种通过字符串建立的关联是不可见的。如果不开启此选项这个预制体就会被误判为“未引用”而建议删除导致运行时加载失败。重要提示开启此选项后扫描时间会显著增加因为工具需要解析Addressables的配置文件。对于大型项目请耐心等待。4.2 扫描AssetReference字段进阶选项在“Analysis Settings”中还有一个“Scan For AssetReferences”选项。这个功能更底层也更容易让人困惑。AssetReference是什么AssetReference是Addressables系统提供的一个序列化类型。你可以在MonoBehaviour或ScriptableObject中声明一个public AssetReference myRef;字段然后在Inspector中像拖拽普通引用一样为其指定一个资产。与直接引用public GameObject prefab;不同AssetReference存储的是资产的GUID和地址它本身不阻止资产被构建时剥离而是通过Addressables系统来管理加载。这个选项解决了什么问题默认情况下AssetDatabase.GetDependencies无法识别AssetReference类型的字段。也就是说如果一个预制体A的唯一引用是来自脚本B中的一个AssetReference字段那么在不开启此选项时预制体A会被判定为“未引用”。开启后的工作原理当勾选“Scan For AssetReferences”后Dependencies Hunter会改变扫描策略。它不再完全依赖AssetDatabase.GetDependencies而是会以文本形式读取资产文件如.prefab, .unity, .asset搜索其中序列化的AssetReference字段所对应的GUID然后将这个GUID对应的资产加入到依赖关系中。代价与决策扫描速度文本解析比API调用慢得多。对于拥有成千上万个预制体和脚本化对象的项目扫描时间可能从几分钟延长到十几分钟甚至更久。准确性理论上更准确能捕获更多隐藏的引用。我的建议是不要默认开启这个选项。首先进行常规扫描不勾选此选项并清理。如果在清理后运行时发现某些通过AssetReference引用的资产丢失了再开启此选项进行一次“终极验证”扫描。在大多数项目中如果规范地使用了Addressables重要的AssetReference资产通常也会被加入到Addressables组中从而被“Detect Addressables”选项保护。因此“Scan For AssetReferences”更像是一个兜底的安全检查。5. 结果分析与安全删除操作流程扫描完成后面对可能成百上千条的“未引用资产”列表如何安全、高效地处理是关键。鲁莽的删除会导致项目损坏。5.1 解读结果列表结果列表的每一列都提供了重要信息Name/Path资产名称和完整路径。这是定位资产的主要依据。Type资产类型Texture, Material, Prefab等。类型可以帮助你快速判断。例如一堆“TextAsset”可能是临时导入的JSON或XML配置文件而“Material”则需谨慎可能被代码动态创建引用。Size资产在磁盘上的大小通常是未压缩的大小。按此列排序优先处理那些占用空间巨大的资产如高清纹理、音频文件清理它们能获得最显著的体积优化效果。Refs引用计数。对于“未引用资产”视图这里始终是0。如果你关闭了“Show Unreferenced Assets Only”则会显示所有资产的引用数。5.2 三步审查法避免误删直接点击“Delete Selected”是高风险行为。请遵循以下审查流程第一步类型与路径筛选审查Resources和StreamingAssets如果之前没有在忽略模式中添加这些路径现在要格外小心。列表中的Resources资产你需要回忆或搜索代码中是否有对应的Resources.Load调用。关注脚本化对象ScriptableObject和配置表这些资产可能被代码通过路径或名称动态加载。检查其文件名是否在代码的常量定义或配置文件中出现。忽略编辑器相关资产扩展名为.cs,.asmdef,.editor编辑器脚本等的文件通常可以安全忽略或加入忽略列表。第二步样本抽查与验证在结果列表中右键点击某个你怀疑的资产比如一个材质球选择“[DH] Find References in Project”。这个上下文菜单功能是Dependencies Hunter另一个强大之处。如果工具弹窗显示“No references found”并且你确认它不在Addressables中那么它很可能是安全的。如果工具找到了引用者但主扫描却没发现这可能是“Scan For AssetReferences”未开启导致的漏报。此时你应该将这个资产从删除列表中排除并考虑是否需要开启该选项重新扫描。第三步备份与试删除版本控制提交在执行任何删除操作前确保当前所有更改已提交到Git、SVN或Perforce等版本控制系统。这是最重要的安全网。选择性备份对于仍然不确定但占用空间大的资产可以手动将其从Assets目录移动到一个临时文件夹如_ToDeleteBackup外部。不要只是重命名或移到Assets内的另一个位置因为Unity的meta文件引用可能依然存在。分批删除不要一次性全选删除。可以按类型或按文件夹分批操作。例如先删除所有确认为未使用的纹理测试游戏运行无误后再删除材质以此类推。运行测试删除一批资产后务必在编辑器中运行游戏遍历主要功能场景检查是否有贴图丢失紫色、预制体引用丢失显示为“Missing”或运行时加载错误。5.3 使用“查找引用”功能进行逆向侦查除了从“未引用”列表入手你还可以主动侦查特定资产。在Project窗口选中一个或多个资产右键选择“[DH] Find References in Project”会打开一个“Selected Assets”窗口详细列出选中资产被哪些其他资产所引用。这个功能的典型应用场景疑惑你觉得某个老旧的模型Prefab应该没用了但不敢删。操作选中该Prefab使用“查找引用”。结果发现它被一个名为“OldLevelDesign”的场景引用而这个场景在构建设置中早已被移除。结论你可以安全地删除这个Prefab或者连同那个废弃场景一起清理。这个功能是理解项目资产关联关系的利器尤其适合在接手遗留项目时进行架构梳理。6. 常见问题、报错与解决方案实录在实际使用中你几乎一定会遇到下面这些问题。这里记录了我踩过的坑和总结的解决方案。6.1 扫描过程卡住或异常缓慢现象点击“Analyze Project”后进度条缓慢蠕动编辑器无响应甚至卡死。原因与解决方案项目资产量巨大这是最主要的原因。首次扫描或长时间未扫描后工具需要构建完整的依赖图。方案耐心等待。对于超大型项目超过10GB资产首次扫描可能需要30分钟以上。可以尝试在非工作时间进行。开启了“Scan For AssetReferences”如前所述此选项会大幅降低扫描速度。方案除非必要否则关闭此选项进行常规扫描。磁盘I/O或杀毒软件干扰工具需要频繁读取磁盘上的资产文件。方案将Unity项目目录添加到杀毒软件的排除列表。使用SSD硬盘能显著提升速度。内存不足构建大型依赖图会消耗大量内存。方案关闭不必要的编辑器窗口和应用增加系统虚拟内存。如果项目过大考虑分模块扫描通过忽略模式排除已清理的模块。6.2 扫描结果不准确误报/漏报现象工具报告某个资产未引用但你确信它在游戏中被使用了或者反过来某个明显无用的资产却没被扫出来。原因与解决方案问题类型可能原因解决方案误报 (False Positive)资产被标记为未引用但实际有用。1.动态加载通过Resources.Load,AssetBundle.LoadAsset,Addressables.LoadAssetAsync加载。2.代码生成引用在运行时通过Resources.Load或Addressables加载路径是字符串拼接的。3.Shader或Graph中引用在Shader Graph或VFX Graph中引用的纹理依赖分析可能不完整。4.AssetReference未扫描资产仅被AssetReference字段引用且未开启对应选项。1. 确保资产位于Resources文件夹或已被添加到Addressables组并开启“Detect Addressables”。2. 将资产路径或其父文件夹添加到忽略模式。3. 手动检查Shader/Graph或将此类资产加入忽略列表。4. 开启“Scan For AssetReferences”重新扫描或手动将资产移出删除列表。漏报 (False Negative)资产实际无用但未被标记。1.循环引用资产A引用BB又引用A可能通过复杂的中间链形成闭环导致两者在依赖图中都有入度。2.编辑器脚本引用资产被某个编辑器工具类引用但该工具类本身不参与运行时。3.忽略模式过于宽泛设置的忽略正则表达式匹配了不该忽略的资产路径。1. 工具通常能处理简单循环引用。对于复杂情况需要手动审查。可以尝试临时移除其中一个资产看另一个是否会变成未引用。2. 检查引用该资产的脚本是否在Editor文件夹下。如果是可以放心清理该资产或将该编辑器脚本也加入清理列表。3. 复查并收紧忽略模式的正则表达式。6.3 删除资产后引发编译错误或运行时错误现象删除资产后Unity控制台报错如脚本编译错误或游戏运行时出现粉色材质、Missing预制体。原因与解决方案删除了被脚本直接引用的资产例如一个public Material defaultMat;字段在Inspector中引用了某个材质球你删除了这个材质球。预防删除前使用右键的“[DH] Find References in Project”功能检查资产是否被任何脚本.cs文件引用。补救从版本控制中恢复被删除的资产或在Inspector中为丢失的引用重新赋值。删除了Shader或Compute Shader文件导致使用该Shader的材质变粉。预防对Shader、Compute Shader、HLSL文件等保持最高警惕。除非你百分百确定所有使用它的材质都已废弃。补救恢复Shader文件或为受影响的材质重新指定Shader。删除了Addressables中注册的资产但游戏运行时需要加载它。预防务必开启“Detect Addressables”选项并确保Addressables配置本身是正确的。补救恢复资产或从Addressables组中移除该资产的条目。6.4 工具窗口无法打开或功能缺失现象菜单中没有“Dependencies Hunter”选项或窗口打开是空的/报错。原因与解决方案脚本编译错误如果项目中有其他脚本错误可能导致编辑器工具无法正常加载。方案解决所有编译器错误重启Unity编辑器。安装位置错误手动复制的DependenciesHunter.cs脚本没有放在Assets目录下的任意一个Editor文件夹内。方案确保脚本路径类似于Assets/Editor/DependenciesHunter.cs或Assets/MyTools/Editor/DependenciesHunter.cs。只有放在Editor文件夹下的脚本才能在编辑器中运行。Unity版本兼容性问题虽然工具兼容性较好但极旧的Unity版本可能缺少某些API。方案检查GitHub仓库的Issues或说明确认支持的Unity版本。考虑升级Unity或寻找旧版本的工具分支。7. 高级技巧与集成到工作流将Dependencies Hunter从“偶尔使用的清理工具”升级为“项目健康守护流程”的一部分能带来长期收益。7.1 创建自定义扫描预设对于大型项目不同的模块或阶段可能需要不同的扫描策略。你可以通过脚本扩展来创建一键扫描预设。在Assets/Editor/下创建一个新脚本例如DependencyScanPresets.cs。利用DependenciesHunter类的静态方法或反射调用来预设参数并启动扫描。示例你可以创建一个“快速扫描”菜单它忽略所有测试资源和第三方插件再创建一个“深度扫描”菜单它包含所有资源但开启Addressables检测。这需要一定的编辑器脚本编写能力但一旦设置好能为团队提供极大的便利。7.2 与CI/CD管道集成在团队开发中可以在每次打包前或每日构建时自动运行Dependencies Hunter扫描并将结果报告如未引用资产列表及其总大小输出为日志或发送到协作平台如Slack、钉钉。思路使用Unity命令行模式 (-batchmode -quit) 执行一个编辑器脚本。在该脚本中调用Dependencies Hunter的扫描API获取结果。将结果资产路径、大小格式化为文本或JSON。如果未引用资产的总大小超过某个阈值例如100MB则令构建失败或发出警告。这样可以防止未被注意到的资源悄悄增大包体把优化工作左移。7.3 处理特殊资产类型Terrain Data地形数据地形资源与其关联的细节纹理、树木原型等资产的引用关系有时比较隐蔽。Dependencies Hunter有一个实验性的“Scan Terrain Data”选项可能在代码中UI未直接暴露可以更彻底地扫描地形引用。如果你大量使用地形可以查阅源码确认。动画控制器Animator Controller和动画片段Animation Clip它们的引用关系通常能被正确捕获。但要注意状态机中通过脚本控制的条件或事件其关联的资源可能无法被静态分析。ScriptableObject数据资产这是误删的重灾区。务必确认这些数据资产是否被代码通过Resources.Load或Addressables加载或者是否被其他ScriptableObject引用。最好的实践是为重要的数据资产建立清晰的加载路径和架构避免隐式引用。使用Dependencies Hunter的最高境界不是等项目臃肿了才来一次大扫除而是将其作为日常开发习惯的一部分。在每次提交新资源、每次重构旧模块后都花几分钟扫描一下相关目录及时清理产生的“垃圾资产”。这就像每天整理办公桌虽然琐碎但能长期保持高效和清爽。工具本身是冰冷的但结合清晰的工作流程和团队规范它就能成为保障项目代码库和资源库健康的强大助力。