3.YooAsset工具窗口
3.1 知识点
YooAsset 的菜单功能列表
Home Page:跳转至 YooAsset 官方主页、文档或相关介绍页面,方便用户获取工具说明与支持。 查看官方文档网站
AssetBundle 相关工具:
- AssetBundle Collector:资源配置界面。收集项目资源,确定哪些资源需要打包成 AssetBundle。
- AssetBundle Builder:资源构建界面。构建工具,用于生成 AssetBundle 包,配置打包参数。
- AssetBundle Reporter:构建报告界面。生成构建报告,展示 AssetBundle 依赖关系、大小等信息,便于分析优化。
- AssetBundle Debugger:调试工具,用于排查 AssetBundle 加载、依赖错误等运行时问题。
AssetArt 相关工具:
- AssetArt Scanner:扫描项目美术资源(如模型、贴图),检测格式、尺寸等规范问题。
- AssetArt Reporter:生成美术资源分析报告,汇总扫描结果,辅助资源管理与优化。
AssetBundle Collector 资源配置界面
顶部功能栏细节
- Fix修复按钮:当配置中的文件夹位置变动时,修正资源路径关联,确保资源引用正常。比如默认找不到资源路径,点击修复按钮后找到了。
- 导入按钮:导入保存的 XML 配置文件,快速复用历史配置,减少重复操作。
- 导出按钮:将当前配置数据导出为 XML 文件,便于备份、团队协作共享配置。
原来找不到,点击修复按钮后找到了
全局设置项解析
Show Package:控制是否展示资源包列表视图,勾选后直观呈现项目资源包结构。一般默认只有一个DefaultPackage。
Show Editor Alias:是否显示为中文模式。切换界面语言显示模式,开启后以中文展示相关功能说明。
Unique Bundle Name:为资源包名添加
PackageName
前缀,多Package
场景下避免包名冲突,建议开启。
包裹设置项说明
- Enable Addressable:启用可寻址资源定位系统,支持代码加载资源,同时兼容全路径加载方式。相当于可以使用全路径加载,建议开启!。
- Location To Lower:使资源定位地址大小写不敏感,简化资源加载时的地址匹配逻辑。
- Include Asset GUID:在资源清单中记录资源 GUID 信息,精准追踪管理资源。
- Auto Collect Shaders:自动将所有着色器打包到独立资源包,优化着色器管理与加载效率。就是开启后,系统会自动把所有着色器打包到一个独立的 “shader 资源包” 里;不用你手动整理,加载时更高效(比如切换场景时,着色器不用重复加载),管理也更方便。
- File Ignore Rule:设置全局文件忽略规则(支持扩展),如原生文件配置可选择
RawFileIgnoreRule
过滤特定文件。相当于一个筛选规则比如选 RawFileIgnoreRule,可以设置哪些文件 “不用处理”(比如某些原生格式、临时文件);这样打包的时候,这些文件会被过滤掉,避免包体变大或者塞进去没用的东西。
资源分组配置细节
Active Rule:分组激活规则(支持自定义扩展)。用于控制 资源分组是否生效(是否参与打包、加载等流程)。内置规则如
EnableGroup
(启用分组)、DisableGroup
(禁用分组),DisableGroup示例代码如下:using YooAsset; // 必须引入YooAsset命名空间 public class DisableGroup : IActiveRule { public bool IsActiveGroup(GroupData groupData) { // 这里可以扩展更复杂的逻辑,比如: // if (groupData.GroupName == "battle") return false; // 根据分组名称判断 // 现在是固定返回false,让分组永远不激活 return false; } }
也可以自己实现继承IActiveRule的类,自定义IsActiveGroup逻辑。这样在这个下拉框就可以选择里自定义的那个类,走自定义规则。Grouper Name:定义分组名称(如
battle
),标识资源分组用途。Grouper Desc:添加分组备注信息,说明分组内容,方便团队协作理解。
Asset Tags:为分组内资源添加分类标签(多标签用分号分隔,如
level1;level2
),便于资源筛选。
搜集器配置详解
Collect Path:指定需要收集的资源路径,可以是文件夹(如 Assets/Res/UI)或单个文件(如 Assets/Res/Models/player.prefab)。只有该路径下的资源会被当前搜集器处理,避免无关资源混入。
Collector Type:定义收集器类型:
- MainAssetCollector: 收集资源并写入资源清单(Manifest),支持通过代码加载(如 YooAsset.Load)。适用于大部分业务资源(UI、模型、音效等需主动加载的资源)。
- StaticAssetCollector: 收集资源但不写入清单,仅用于定制化打包(如内置到安装包的基础资源)。适用于无需代码动态加载的固定资源(如启动图、全局配置)。
- DependAssetCollector:自动收集 “主资源依赖的资源”(如材质依赖的纹理、预制体依赖的动画),未被引用的依赖会自动剔除。适用于处理资源间的依赖关系,避免手动收集依赖导致的遗漏或冗余。
AddressRule:可寻址规则(支持自定义)。或者说是资源的 “加载地址生成规则”。定义代码加载资源时使用的 “地址字符串”,决定如何通过字符串定位资源。
AddressByFileName:按文件名生成地址,只取 文件名(去掉扩展名) 作为地址。适用于资源路径唯一(如所有资源放在同一文件夹),或确保同名文件不会出现。例如Assets/Res/UI/btn.png和Assets/Res/Icon/btn.png地址都是btn,会冲突。
[DisplayName("定位地址: 文件名")] public class AddressByFileName : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { return Path.GetFileNameWithoutExtension(data.AssetPath); } }
AddressByFolderAndFileName:按文件夹+文件名生成地址,取“文件夹路径(相对资源根目录)+ 文件名(去掉扩展名)”作为地址。适用于需要区分不同文件夹下的同名文件,避免跨文件夹冲突。例如Assets/Res/UI/btn.png地址是UI/btn,Assets/Res/Icon/btn.png地址是Icon/btn,不会冲突;但Assets/Res/UI/btn.png和Assets/Res/UI/btn.jpg地址都是UI/btn,会冲突。
[DisplayName("定位地址: 文件夹名_文件名")] public class AddressByFolderAndFileName : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { string fileName = Path.GetFileNameWithoutExtension(data.AssetPath); FileInfo fileInfo = new FileInfo(data.AssetPath); return $"{fileInfo.Directory.Name}_{fileName}"; } }
AddressByGroupAndFileName:按分组+文件名生成地址,取“资源所属分组名称 + 文件名(去掉扩展名)”作为地址。适用于多业务分组管理资源,通过分组隔离同名文件。例如属于“UI分组”的Assets/Res/UI/btn.png地址是UI/btn,属于“Icon分组”的Assets/Res/Icon/btn.png地址是Icon/btn,不会冲突;但同一分组内的Assets/Res/UI/btn.png和Assets/Res/UI/btn.jpg地址都是UI/btn,会冲突。
[DisplayName("定位地址: 分组名_文件名")] public class AddressByGroupAndFileName : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { string fileName = Path.GetFileNameWithoutExtension(data.AssetPath); return $"{data.GroupName}_{fileName}"; } }
AddressDisable:禁用可寻址地址,生成空值或无效标识(如固定字符串“disable”),使资源无法通过地址直接加载。适用于仅作为其他资源的依赖项(如材质引用的纹理、预制体依赖的动画),无需单独加载的资源。例如任何资源使用此规则后,地址均为无效值,调用YooAsset.LoadAsset(“xxx”)会加载失败。
[DisplayName("定位地址: 禁用")] public class AddressDisable : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { return string.Empty; } }
AddressByFileNameAndExt:按文件名+扩展名生成地址,保留“文件名+扩展名”作为完整地址。适用于同文件夹内需要区分不同格式的同名文件(如图片和脚本同名)。例如Assets/Res/UI/btn.png地址是btn.png,Assets/Res/UI/btn.jpg地址是btn.jpg,不会冲突;但Assets/Res/UI/btn.png和Assets/Res/Icon/btn.png地址都是btn.png,会冲突。
[DisplayName("定位地址: 文件名.智能尾缀")] public class AddressByFileNameAndExt : IAddressRule { public string GetAssetAddress(AddressRuleData data) { var ext = Path.GetExtension(data.AssetPath); if (ext == ".asset") { var a = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(data.AssetPath); if (a == null) return ".errortype"; var type = a.GetType(); var dt = Path.GetFileNameWithoutExtension(data.AssetPath); return dt + $".{type.Name.ToLowerInvariant()}"; } return Path.GetFileName(data.AssetPath); } }
AddressByFullPath:需要自定义添加代码,但其实完全没必要,因为开启Enable Addressable就行。如果按资源完整路径生成地址,直接返回
data.AssetPath
(资源在项目中的完整路径)作为地址。适用于需要绝对唯一地址、不希望任何冲突的场景,尤其适合资源路径规范严格的项目。例如Assets/Res/UI/btn.png地址是Assets/Res/UI/btn.png,Assets/Res/Icon/btn.png地址是Assets/Res/Icon/btn.png,完全不会冲突(因为项目中每个资源的完整路径必然唯一);即使同文件夹内有同名不同扩展名的资源(如Assets/Res/UI/btn.png和Assets/Res/UI/btn.jpg),地址也分别为完整路径,同样不冲突。但需注意:此规则生成的地址较长,且如果资源移动路径(如从UI文件夹移到Icon文件夹),代码中对应的加载地址也需要同步修改,维护成本略高。[DisplayName("定位地址: 完整路径")] public class AddressByFullPath : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { // 直接返回资源的完整路径作为地址,利用路径唯一性避免冲突 return data.AssetPath; } }
PackRule:打包规则(支持自定义)。决定资源如何合并为 AssetBundle 包,直接影响 加载效率(包体大小 → 加载时间,包数量 → 并发请求数)。通过规则类定义“资源包的划分逻辑”,即 哪些资源该打进同一个包。
DefaultPackRule
(打包规则配置类)
下面的规则依赖DefaultPackRule
统一管理包的后缀、默认名称:public class DefaultPackRule { /// <summary> /// AssetBundle文件的后缀名 /// </summary> public const string AssetBundleFileExtension = "bundle"; /// <summary> /// 原生文件的后缀名 /// </summary> public const string RawFileExtension = "rawfile"; /// <summary> /// 默认的Unity着色器资源包名称 /// </summary> public const string ShadersBundleName = "unityshaders"; /// <summary> /// 默认的Unity脚本资源包名称 /// </summary> public const string MonosBundleName = "unitymonos"; public static PackRuleResult CreateShadersPackRuleResult() { PackRuleResult result = new PackRuleResult(ShadersBundleName, AssetBundleFileExtension); return result; } public static PackRuleResult CreateMonosPackRuleResult() { PackRuleResult result = new PackRuleResult(MonosBundleName, AssetBundleFileExtension); return result; } }
PackSeparately
(资源包名: 文件路径)- 作用:每个资源单独打包,包名由文件路径处理生成(小写、替换分隔符,确保唯一性)。适用于 超大资源(如高清视频) 或 需精准热更(仅更新单个资源) 的场景。
- 例子:
Assets/UIPanel/Shop/Image/backgroud.png
→assets_uipanel_shop_image_backgroud.bundle
Assets/UIPanel/Shop/View/main.prefab
→assets_uipanel_shop_view_main.bundle
(不同资源单独成包,互不影响)。
- 代码实现:
[DisplayName("资源包名: 文件路径")] public class PackSeparately : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string bundleName = PathUtility.RemoveExtension(data.AssetPath); // 移除扩展名,统一格式 return new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension); } }
PackDirectory
(资源包名: 父类文件夹路径)- 作用:同一文件夹下的资源合并打包,包名 = 文件夹路径(相对项目根目录)。适用于 按模块聚合资源(如 UI 模块、战斗模块各自成包,提升模块内资源复用率)。
- 例子:
Assets/UIPanel/Shop/Image
文件夹下的backgroud.png
、icon.png
→ 统一打进assets_uipanel_shop_image.bundle
(同文件夹资源合并)。
- 代码实现:
[DisplayName("资源包名: 父类文件夹路径")] public class PackDirectory : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string bundleName = Path.GetDirectoryName(data.AssetPath); // 取文件所在文件夹路径 return new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension); } }
PackTopDirectory
(资源包名: 收集器下顶级文件夹路径)- 作用:以 收集器内的“顶级文件夹” 为单位打包(若资源嵌套多级文件夹,取最上层文件夹名)。适用于 合并多级子文件夹资源,但希望按顶层模块聚合(如所有 UI 相关资源打一个包)。
- 例子:
- 收集器路径为
Assets/UIPanel
,资源Assets/UIPanel/Shop/Image/backgroud.png
、Assets/UIPanel/Shop/View/main.prefab
→ 顶级文件夹是Shop
,统一打进assets_uipanel_shop.bundle
(多级子文件夹合并到顶级文件夹)。
- 收集器路径为
- 代码实现:
[DisplayName("资源包名: 收集器下顶级文件夹路径")] public class PackTopDirectory : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string assetPath = data.AssetPath.Replace(data.CollectPath, string.Empty).TrimStart('/'); string[] splits = assetPath.Split('/'); if (splits.Length == 0 || Path.HasExtension(splits[0])) throw new Exception($"未找到顶级文件夹:{assetPath}"); string bundleName = $"{data.CollectPath}/{splits[0]}"; // 收集器路径 + 顶级文件夹名 return new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension); } }
PackCollector
(资源包名: 收集器路径)- 作用:当前收集器的所有资源合并为一个包,包名 = 收集器路径(相对项目根目录)。适用于 资源强关联(如一个功能模块的所有资源) 或 资源量小,需最小化包数量(减少加载请求)。
- 例子:
- 收集器路径为
Assets/UIPanel
,该路径下的btn.png
、panel.prefab
、Shop/btn.png
→ 全部打进assets_uipanel.bundle
(收集器内资源全合并)。
- 收集器路径为
- 代码实现:
[DisplayName("资源包名: 收集器路径")] public class PackCollector : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string bundleName = AssetDatabase.IsValidFolder(data.CollectPath) ? data.CollectPath // 收集器是文件夹,直接用路径 : PathUtility.RemoveExtension(data.CollectPath); // 收集器是文件,移除扩展名 return new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension); } }
PackGroup
(资源包名: 分组名称)- 作用:按 资源分组名称 打包,同一分组的资源合并为一个包(分组在 YooAsset 配置中定义)。适用于 多业务分组管理(如不同团队维护独立分组,确保分组内资源统一打包)。
- 例子:
- 资源分组为
BattleGroup
,旗下的sword.prefab
、effect.particle
→ 打进BattleGroup.bundle
(同分组资源合并)。
- 资源分组为
- 代码实现:
[DisplayName("资源包名: 分组名称")] public class PackGroup : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string bundleName = data.GroupName; // 直接用分组名称作为包名 return new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension); } }
PackRawFile
(打包原生文件)- 作用:资源以 原生格式(如 txt、json)直接打包,不经过 Unity 引擎处理(保留文件原始内容),包后缀为
rawfile
。适用于 需直接读取原始文件内容(如配置文件、自定义格式数据),避免 Unity 序列化干扰。 - 例子:
Assets/Res/Config/game.json
→Assets/Res/Config/game.json.rawfile
(加载时按原生文件处理)。
- 代码实现:
[DisplayName("打包原生文件")] public class PackRawFile : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string bundleName = data.AssetPath; // 包名保留原路径 return new PackRuleResult(bundleName, DefaultPackRule.RawFileExtension); } }
- 作用:资源以 原生格式(如 txt、json)直接打包,不经过 Unity 引擎处理(保留文件原始内容),包后缀为
PackVideoFile
(打包视频文件)- 作用:视频文件 单独打包,包后缀保留原视频格式(如 mp4、mov),便于播放器直接读取。适用于 视频资源需原生格式加载(如 Unity 视频播放器直接播放),避免格式转换。
- 例子:
Assets/Res/Video/intro.mp4
→Assets/Res/Video/intro.mp4.mp4
(后缀为原格式mp4
)。
- 代码实现:
[DisplayName("打包视频文件")] public class PackVideoFile : IPackRule { PackRuleResult IPackRule.GetPackRuleResult(PackRuleData data) { string fileExtension = Path.GetExtension(data.AssetPath).Substring(1); // 提取扩展名(如 mp4) string bundleName = data.AssetPath; return new PackRuleResult(bundleName, fileExtension); } }
PackShader
(打包着色器文件)- 作用:所有着色器(Shader)合并为统一包,包名为
unityshaders
,优化着色器加载效率(减少冗余编译)。适用于 项目着色器数量多,需批量加载,降低运行时着色器编译开销。 - 例子:
Assets/Shaders/Lit.shader
、Assets/Shaders/Transparent.shader
→ 统一打进unityshaders.bundle
(着色器集合打包)。
- 代码实现:
[DisplayName("打包着色器文件")] public class PackShader : IPackRule { public PackRuleResult GetPackRuleResult(PackRuleData data) { return DefaultPackRule.CreateShadersPackRuleResult(); // 复用默认着色器包名 } }
- 作用:所有着色器(Shader)合并为统一包,包名为
PackShaderVariants
(打包着色器变种集合文件)- 作用:着色器变种(如同一 Shader 的不同 Pass 变体)合并为统一包,包名为
unityshaders
,减少冗余变体的重复打包。适用于 需合并 Shader 变体,避免同一 Shader 的不同变体分散打包导致的体积膨胀。 - 例子:
Assets/Shaders/Lit variants.shadervariants
→ 打进unityshaders.bundle
(变种集合打包)。
- 代码实现:
[DisplayName("打包着色器变种集合文件")] public class PackShaderVariants : IPackRule { public PackRuleResult GetPackRuleResult(PackRuleData data) { return DefaultPackRule.CreateShadersPackRuleResult(); // 复用默认着色器包名 } }
- 作用:着色器变种(如同一 Shader 的不同 Pass 变体)合并为统一包,包名为
FilterRule:过滤收集的资源类型。决定当前搜集器 “只收集哪些类型的资源”,过滤掉无关资源(如临时文件、非目标类型文件)。
- 内置如
CollectScene
(只收集场景文件),示例:public class CollectScene : IFilterRule { public bool IsCollectAsset(FilterRuleData data) { return Path.GetExtension(data.AssetPath) == ".unity"; } }
- 内置如
UserData:自定义数据,辅助定制
AddressRule
和PackRule
,满足个性化需求。在 PackRule 中,可通过 data.UserData 获取配置的参数(如 maxSize=5),动态调整打包策略。Asset Tags:为当前搜集器收集的资源统一添加标签(如 activity;2024),与分组的 Asset Tags 配合,便于后续按标签筛选资源(如统计所有 “活动” 标签的资源)。
AssetBundle Builder 资源构建界面
界面功能模块
Build Package:资源包裹列表,通过下拉选择确定需构建的资源包裹范围。
Build Pipeline:构建管线列表,包含多种类型:
- EditorSimulateBuildPipeline:编辑器模拟构建管线。在编辑器内 模拟打包流程,生成资源清单(Manifest)但 不实际生成 AssetBundle 文件,快速验证资源依赖和寻址规则。比如开发阶段修改资源后,想快速检查 “哪些资源会被打包、地址是否冲突”,无需等待真实打包(真实打包可能耗时数分钟)。适用于开发调试(验证资源配置、依赖关系);快速迭代,避免频繁全量打包的时间消耗。
- BuiltinBuildPipeline:内置构建管线,常规构建使用。使用 Unity 原生的 AssetBundle 构建逻辑,常规项目默认可选择。一般项目无特殊打包需求(如加密、定制 Bundle 结构),可以直接用此管线构建生产环境的资源包。
- ScriptableBuildPipeline:可编程构建管线(Unity 2021.3+推荐),允许开发者控制打包流程。可以通过 自定义脚本控制打包全流程(如资源加密、拆分 Bundle、注入自定义数据),灵活度极高。比如对 AssetBundle 进行加密(打包时自动加密,加载时解密);按自定义规则拆分 Bundle(如按资源大小、标签动态分组)。适用于大型项目需深度定制打包流程(如加密、性能优化)。
- RawFileBuildPipeline:原生文件构建管线,处理Unity无法识别的资源(如FMOD音频文件)。直接 复制原生文件(不经过 Unity 处理) 到输出目录,保留文件原始格式(如自定义二进制、FMOD 音频文件)。
Build Output:构建输出目录,根据Unity当前平台划分构建结果,便于管理不同平台资源。
Build Version:设置构建的资源包版本,用于标识补丁包等内容。
Clear Build Cache:清理构建缓存,勾选则重新构建所有资源包;不勾选启用增量打包,提升构建速度。
Use Asset Depend DB:开启后使用资源依赖关系数据库,加快资源收集与构建效率。
Encryption:加密类列表,支持自定义加密(需实现
IEncryptionServices
接口),包含文件偏移、内存、流等解密加载方式。Compression:设置资源包压缩方式,优化包体大小。
File Name Style:定义输出资源包文件名样式,如
HashName
(哈希值)、BundleName
(资源包名)、BundleName_HashName
(资源包名+哈希值)。
Copy Buildin File Option:首包资源拷贝方式:
- None:不拷贝文件。首包目录不包含任何资源,所有资源依赖后续热更新下载。安装包体积最小,但弱网环境可能无法加载资源,依赖热更系统兜底。适用于纯热更游戏(如长期运营的网游),首包仅含启动代码,资源全通过网络动态加载。
- ClearAndCopyAll:清空后拷贝所有文件。先清空首包目录原有资源,再将所有符合构建条件的资源拷贝进去。首包包含完整资源,无需依赖热更,但安装包体积最大,构建时间较长。适用于游戏大版本更新(如 UI 全面改版、核心玩法重构),需替换首包内所有旧资源,确保首包资源为最新全量。
- ClearAndCopyByTags:清空后按资源标签拷贝。先清空首包目录,再 仅拷贝带指定标签的资源(标签需在资源配置中预先定义)。首包体积可控(仅含核心资源),适合标签化管理清晰的项目,但需确保标签覆盖所有必要资源。比如首包仅需 “核心玩法” 资源(如主场景、基础角色,标签为 core),清空旧资源后,将 core 标签的资源集中拷贝进首包。
- OnlyCopyAll:不清空直接拷贝所有文件。保留首包目录原有资源,直接追加拷贝所有新资源(可能导致重复,需谨慎使用)。 相对来说迭代效率高,但长期使用易导致首包体积冗余,需人工清理重复资源。 适用于小版本更新(如修复 Bug、新增少量道具),首包已有基础资源,新增资源直接追加,避免覆盖旧内容(需保证资源地址无冲突)
- OnlyCopyByTags:不清空直接按标签拷贝。保留首包目录原有资源,仅追加拷贝带指定标签的新资源。适合活动资源兜底(首包预先存放部分活动资源,降低热更压力),需维护标签一致性,避免遗漏。比如首包已有 core 标签的核心资源,新增暑期活动资源(标签 activity_summer),仅追加该标签的资源,避免影响核心资源。
构建操作与结果
- 构建执行:点击“构建”按钮启动多节点流程,任一节点错误则构建失败,错误信息可在控制台查看。
- 补丁包:构建成功后,输出目录生成以“资源版本号”命名的补丁包文件夹,包含:
- 资源清单:
DefaultPackage.version
:资源版本文件。DefaultPackage_xxx.hash
:记录资源清单哈希值。DefaultPackage_xxx.json
:Json格式,用于预览信息。DefaultPackage_xxx.bytes
:二进制格式,供程序读取加载。
- 构建报告:
DefaultPackage_xxx.report
,可通过构建报告窗口查看详细构建信息。
- 资源清单:
重要概念与注意事项
- 增量构建:利用Unity资源构建缓存,避免重复构建,提升打包效率。也就是不勾选Clear Build Cache。
首包资源:构建应用时打入首包的资源,存放于
StreamingAssets/yoo/
目录,支持热更新。也就是选择Copy Buildin File Option首包资源拷贝方式。Jenkins自动化构建:参考示例代码配置构建参数(如输出目录、版本、加密等),通过代码执行构建流程,实现自动化。如果需要自动化构建,可以参考如下几个不同构建的代码范例。
SBP构建管线注意事项:需设置内置着色器资源包名称,且与自动收集的着色器资源包名一致,确保构建正确。
using UnityEditor;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;
public static class TestPackageBuilder
{
/// <summary>
/// 构建资源包
/// </summary>
public static PackageInvokeBuildResult BuildPackage(PackageInvokeBuildParam buildParam)
{
string packageName = buildParam.PackageName;
string buildPipelineName = buildParam.BuildPipelineName;
if (buildPipelineName == EBuildPipeline.EditorSimulateBuildPipeline.ToString())
{
//...
}
else if (buildPipelineName == EBuildPipeline.ScriptableBuildPipeline.ToString())
{
string projectPath = EditorTools.GetProjectPath();
string outputRoot = $"{projectPath}/Bundles/Tester_SBP";
// 内置着色器资源包名称
var builtinShaderBundleName = GetBuiltinShaderBundleName(packageName);
//...
}
else if (buildPipelineName == EBuildPipeline.BuiltinBuildPipeline.ToString())
{
//...
}
else if (buildPipelineName == EBuildPipeline.RawFileBuildPipeline.ToString())
{
//...
}
else
{
throw new System.NotImplementedException(buildPipelineName);
}
}
/// <summary>
/// 内置着色器资源包名称
/// 注意:和自动收集的着色器资源包名保持一致!
/// </summary>
private static string GetBuiltinShaderBundleName(string packageName)
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(packageName, uniqueBundleName);
}
}
AssetBundle Reporter 构建报告界面
点击import,选择Report文件
YooAsset 构建报告工具支持查看概览信息、资源对象视图、资源包视图,且仅适配 Unity 2019.4+ 版本。要import后选择打包出来的report文件才能查看。各视图功能如下:
概览视图
- 核心作用:呈现构建报告整体概况,包含资源包数量、资源对象总数、构建耗时、错误与警告统计等关键数据。通过概览可快速判断构建是否成功,是否存在需处理的异常问题(如大量错误/警告),从宏观层面把握构建结果。
资源对象列表视图
- 内容展示:
- 罗列所有参与构建的资源对象,显示资源名称、类型、路径等基础信息。
- 标注每个资源对象依赖的资源包,便于追踪资源与资源包的依赖关系。例如,分析模型资源对材质、纹理资源包的引用,辅助优化资源引用逻辑,避免依赖冗余或缺失。
资源包列表视图
- 内容展示:
- 展示所有生成的资源包,包含资源包名称、大小、版本等信息。
- 列出每个资源包内包含的资源对象,清晰呈现资源包内容构成。通过该视图可校验资源包是否包含预期资源,是否混入无关内容,进而优化资源包划分策略,确保资源打包的合理性与高效性。
AssetBundle Debugger 调试器界面
调试器核心功能
- 作用:在游戏运行时实时监控资源包加载状态,追踪资源对象引用计数,辅助定位资源泄漏问题。
- 资源泄漏定位:通过引用计数与资源包卸载条件,快速识别未释放的资源。
- 性能优化:分析加载耗时与异步任务执行链,优化资源加载策略。
- 依赖关系验证:校验资源包依赖关系,避免冗余加载或错误引用。
平台支持与调试配置
- 支持版本:仅适配 **Unity 2019.4+**。
- 安卓平台调试:
- Unity 2020/2021:直接支持。
- Unity 2019:需通过 ADB 命令转发调试端口:
adb forward tcp:34999 localabstract:Unity-包名
- 真机远程调试:
- 构建安装包时:勾选
Development Build
和Autoconnect Profiler
,确保调试器可连接。
- 构建安装包时:勾选
资源对象列表视图
- 功能:展示当前加载的所有资源对象及其关键信息:
- 资源名称/路径:标识资源唯一性。
- 加载耗时:资源加载耗时(毫秒),定位性能瓶颈。
- 加载状态:如
Loading
、Loaded
、Unloaded
等。 - 引用计数:统计资源被引用的次数,引用计数归零时触发卸载。
- 依赖资源包列表(Depend Bundles):选中资源加载所依赖的资源包,帮助分析资源包依赖链。
资源包列表视图
- 功能:监控当前加载的资源包及其关联信息:
- 资源包名称/大小:标识资源包基础属性。
- 加载状态:如
Loaded
、Unloaded
。 - 引用计数:资源包被引用的次数。
- 使用中的资源(Using Asset):显示该资源包当前正在使用的资源对象列表。
- 引用关系(Reference Bundle):展示哪些资源包引用了当前选中的资源包。
- 资源包卸载条件:
- 资源包的
Using Asset
列表内所有资源引用计数为零。 - 资源包的
Reference Bundle
列表内所有资源包引用计数为零。
- 资源包的
异步操作任务列表视图
- 功能:跟踪所有异步任务执行详情:
- 任务类型:如资源加载、卸载、场景切换等。
- 开始时间/耗时:记录任务启动时间与执行时长。
- 任务状态:如
Running
、Completed
、Failed
。 - 附加调试信息:包括错误日志、操作链上下文等。
- 操作链分析:
- 选中异步任务后,底部显示完整操作链信息,帮助定位任务执行路径中的问题节点。
AssetArt Scanner 资产扫描器
工具界面组成
- 左侧:资产扫描器列表,显示所有可用扫描器。
- 中间:选中扫描器的配置界面,设置扫描规则与参数。
- 右侧:扫描器参数检视界面,展示自定义扫描器的专属配置。
基础操作按钮
- 导入按钮:加载保存的 XML 配置文件,复用历史扫描规则。
- 导出按钮:将当前配置导出为 XML 文件,便于备份或团队共享。
- 扫描所有按钮:执行全部扫描器任务,生成多份扫描报告。
扫描器配置项详解
- Scanner Name:定义扫描器名称(如
TextureScanner
),标识扫描器功能。 - Scanner Desc:添加扫描器备注信息,说明扫描用途或规则。
- Scanner Schema:关联扫描器模式文件(继承
ScannerSchema
的 ScriptableObject)。 - Output Folder:设置报告文件输出目录,默认为
Assets/ScanReports
。 - Collector:指定扫描路径,可配置多个文件夹或文件范围。
扫描器检视界面
- 功能:开发者实现自定义扫描器时,可编写专属参数检视面板。
- 实现方式:继承
SchemaInspector
类,通过 EditorGUI 绘制可视化配置项。
扫描器接口扩展
需继承基类 ScannerSchema
并实现以下核心方法:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset.Editor
{
public abstract class ScannerSchema : ScriptableObject
{
/// <summary>
/// 获取用户指南信息
/// </summary>
public abstract string GetUserGuide();
/// <summary>
/// 运行生成扫描报告
/// </summary>
public abstract ScanReport RunScanner(AssetArtScanner scanner);
/// <summary>
/// 修复扫描结果
/// </summary>
public abstract void FixResult(List<ReportElement> fixList);
/// <summary>
/// 创建检视面板
/// </summary>
public virtual SchemaInspector CreateInspector()
{
return null;
}
}
}
扩展示例(太空战机DEMO中的纹理扫描器)
#if UNITY_2019_4_OR_NEWER
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using YooAsset.Editor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CreateAssetMenu(fileName = "TextureSchema", menuName = "YooAssetArt/Create TextureSchema")]
public class TextureSchema : ScannerSchema
{
/// <summary>
/// 图片最大宽度
/// </summary>
public int MaxWidth = 1024;
/// <summary>
/// 图片最大高度
/// </summary>
public int MaxHeight = 1024;
/// <summary>
/// 测试列表
/// </summary>
public List<string> TestStringValues = new List<string>();
/// <summary>
/// 获取用户指南信息
/// </summary>
public override string GetUserGuide()
{
return "规则介绍:检测图片的格式,尺寸";
}
/// <summary>
/// 运行生成扫描报告
/// </summary>
public override ScanReport RunScanner(AssetArtScanner scanner)
{
// 创建扫描报告
string name = "扫描所有纹理资产";
string desc = GetUserGuide();
var report = new ScanReport(name, desc);
report.AddHeader("资源路径", 600, 500, 1000).SetStretchable().SetSearchable().SetSortable().SetCounter().SetHeaderType(EHeaderType.AssetPath);
report.AddHeader("图片宽度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
report.AddHeader("图片高度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
report.AddHeader("内存大小", 120).SetSortable().SetUnits("bytes").SetHeaderType(EHeaderType.LongValue);
report.AddHeader("苹果格式", 100);
report.AddHeader("安卓格式", 100);
report.AddHeader("错误信息", 500).SetStretchable();
// 获取扫描资源集合
var searchDirectorys = scanner.Collectors.Select(c => { return c.CollectPath; });
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Texture, searchDirectorys.ToArray());
// 开始扫描资源集合
var results = SchemaTools.ScanAssets(findAssets, ScanAssetInternal);
report.ReportElements.AddRange(results);
return report;
}
private ReportElement ScanAssetInternal(string assetPath)
{
var importer = TextureTools.GetAssetImporter(assetPath);
if (importer == null)
return null;
// 加载纹理对象
var texture = AssetDatabase.LoadAssetAtPath<Texture>(assetPath);
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath);
var iosFormat = TextureTools.GetPlatformIOSFormat(importer);
var androidFormat = TextureTools.GetPlatformAndroidFormat(importer);
var memorySize = TextureTools.GetStorageMemorySize(texture);
// 获取错误信息
string errorInfo = string.Empty;
{
// 苹果格式
if (iosFormat != TextureImporterFormat.ASTC_4x4)
{
errorInfo += " | ";
errorInfo += "苹果格式不对";
}
// 安卓格式
if (androidFormat != TextureImporterFormat.ASTC_4x4)
{
errorInfo += " | ";
errorInfo += "安卓格式不对";
}
// 多级纹理
if (importer.isReadable)
{
errorInfo += " | ";
errorInfo += "开启了可读写";
}
// 超大纹理
if (texture.width > MaxWidth || texture.height > MaxHeight)
{
errorInfo += " | ";
errorInfo += "超大纹理";
}
}
// 添加扫描信息
ReportElement result = new ReportElement(assetGUID);
result.AddScanInfo("资源路径", assetPath);
result.AddScanInfo("图片宽度", texture.width);
result.AddScanInfo("图片高度", texture.height);
result.AddScanInfo("内存大小", memorySize);
result.AddScanInfo("苹果格式", iosFormat.ToString());
result.AddScanInfo("安卓格式", androidFormat.ToString());
result.AddScanInfo("错误信息", errorInfo);
// 判断是否通过
result.Passes = string.IsNullOrEmpty(errorInfo);
return result;
}
/// <summary>
/// 修复扫描结果
/// </summary>
public override void FixResult(List<ReportElement> fixList)
{
SchemaTools.FixAssets(fixList, FixAssetInternal);
}
private void FixAssetInternal(ReportElement result)
{
var scanInfo = result.GetScanInfo("资源路径");
var assetPath = scanInfo.ScanInfo;
var importer = TextureTools.GetAssetImporter(assetPath);
if (importer == null)
return;
// 苹果格式
var iosPlatformSetting = TextureTools.GetPlatformIOSSettings(importer);
iosPlatformSetting.format = TextureImporterFormat.ASTC_4x4;
iosPlatformSetting.overridden = true;
// 安卓格式
var androidPlatformSetting = TextureTools.GetPlatformAndroidSettings(importer);
androidPlatformSetting.format = TextureImporterFormat.ASTC_4x4;
androidPlatformSetting.overridden = true;
// 可读写
importer.isReadable = false;
// 保存配置
importer.SetPlatformTextureSettings(iosPlatformSetting);
importer.SetPlatformTextureSettings(androidPlatformSetting);
importer.SaveAndReimport();
Debug.Log($"修复了 : {assetPath}");
}
/// <summary>
/// 创建检视面板对
/// </summary>
public override SchemaInspector CreateInspector()
{
var container = new VisualElement();
// 图片最大宽度
var maxWidthField = new IntegerField();
maxWidthField.label = "图片最大宽度";
maxWidthField.SetValueWithoutNotify(MaxWidth);
maxWidthField.RegisterValueChangedCallback((evt) =>
{
MaxWidth = evt.newValue;
});
container.Add(maxWidthField);
// 图片最大高度
var maxHeightField = new IntegerField();
maxHeightField.label = "图片最大高度";
maxHeightField.SetValueWithoutNotify(MaxHeight);
maxHeightField.RegisterValueChangedCallback((evt) =>
{
MaxHeight = evt.newValue;
});
container.Add(maxHeightField);
// 创建测试列表
#if UNITY_2021_3_OR_NEWER
ReorderableListView reorderableListView = new ReorderableListView();
reorderableListView.SourceData = TestStringValues;
reorderableListView.HeaderName = "测试列表";
container.Add(reorderableListView);
#endif
SchemaInspector inspector = new SchemaInspector(container);
return inspector;
}
}
#endif
扫描报告输出
- 报告内容:包含问题资源路径、错误类型、修复建议等结构化数据。
- 输出格式:默认生成
.json
文件,在Asset目录下,支持第三方工具解析或二次处理。
典型应用场景
- 美术规范检查:验证纹理尺寸、模型面数等是否符合项目标准。
- 资源冗余检测:扫描重复资源或未引用资产,优化包体体积。
- 自动化修复:批量修改资源导入设置(如压缩格式、Mipmap开关)。
AssetArt Reporter 资产扫描报告
报告核心价值
- 问题精准定位:通过多维度过滤快速定位异常资源。
- 自动化修复:结合扫描器
FixResult
方法实现批量修复,提升效率。 - 团队协作:导出/导入报告文件,便于跨部门协同处理资源问题。
核心功能模块
报告导入与导出
- 单文件导入(Import):加载单个扫描报告文件(
.json
格式),查看详细扫描结果。 - 多文件合并导入(Multi-Import):同时导入多个报告文件并合并显示(需确保扫描器一致,避免数据冲突)。
- 选择性导出(Export Select):勾选需要导出的元素,将关联资源文件拷贝至指定目录,便于批量处理问题资源。
问题修复功能
- 一键修复所有(Fix All):自动修复所有未通过元素(自动排除白名单和隐藏元素)。
- 选择性修复(Fix Select):修复勾选的元素(包含白名单和隐藏元素),用于精细化修复操作。
显示控制选项
- 显示/隐藏元素:通过“眼睛”图标开关控制隐藏元素的显隐。
- 显示通过元素:勾选后展示扫描通过的资源项,用于完整性校验。
- 显示白名单元素:展示已加入白名单的例外资源,避免重复扫描干扰。
注意:该工具仅支持 Unity 2019.4+ 版本。
搜索栏高级语法
通用关键字搜索
直接输入文件名、路径片段等关键词,快速过滤匹配项:
example_texture
Assets/Art/Characters
指定项关键字搜索
通过 字段名:关键词
格式精确搜索特定字段内容(冒号为英文小写):
错误信息:安卓格式不对
资源类型:Texture
指定项数值比较
使用 字段名 比较符 数值
格式进行范围筛选(**支持 =, >, >=, <, <=
**):
内存大小=1024 // 等于 1024 KB
图片宽度>1024 // 宽度大于 1024 像素
图片高度<=2048 // 高度小于等于 2048 像素
操作示例场景
定位纹理格式问题:
错误信息:ETC2不支持
筛选出所有因 ETC2 压缩格式导致问题的纹理资源。
检测超大资源:
内存大小>2048
查找内存占用超过 2MB 的资源,优化包体体积。
批量修复白名单资源:
- 勾选白名单元素 → 点击
Fix Select
,将问题资源标记为例外,避免后续扫描重复报警。
- 勾选白名单元素 → 点击
示例工程中的配置文件
这些是 YooAsset 示例工程里随包放的配置资产与样例脚本,它们全都属于编辑器期资源(不会进运行包),主要用于:
- 保存 AssetBundle 收集/打包规则
- 保存 美术扫描器 的配置与阈值
- 备份/导入导出 收集规则
你可以把它们统一搬到自己的目录,例如:Assets/XX/Setting/YooAsset/
位置并不强制;YooAsset 是按资源类型查找这些资产,不依赖固定路径。移动后若窗口提示丢失,点一次 Fix 即可恢复引用。
文件一览与用途
AssetBundleCollectorSetting.asset
(必须有,唯一)
作用:YooAsset 收集/打包规则的总配置(ScriptableObject)。
- 内含:Packages → Groups → Collectors、地址/打包/过滤/标签等所有规则。
何时生成:第一次打开 AssetBundle Collector 窗口并点击 Fix / Save 时自动创建;或新增 Package/Group 后保存。
放哪都行:建议放到
Assets/LoL/Setting/YooAsset/AssetBundleCollectorSetting.asset
版本管理:务必提交(含
.meta
),团队协作靠它保持规则一致。移动后:如果 Collector 窗口左上角变红,可点 Fix 让窗口重新定位到该资产。
AssetBundleCollectorConfig
(可选的备份/交换格式)
作用:导入/导出 收集规则使用的文本/配置文件(示例里是 XML / JSON 之一)。
如何生成:打开 AssetBundle Collector → 右上角 Export;要恢复用 Import。
是否必须:不是必须;它只是备份/交换介质,运行与打包都不读取它。
最佳实践:
- 团队协作场景保留它,便于做“规则快照”和比对;
- 个人项目可以不保留,仅提交
AssetBundleCollectorSetting.asset
即可。
AssetArtScannerSetting.asset
(可选)
- 作用:美术规范扫描器的统一配置(面板里创建的各个 Scanner、扫描范围、输出目录等)。
- 何时生成:打开 AssetArt Scanner 窗口,配置后点击 Save / Export 时创建。
- 是否必须:按需使用;你不用扫描器可不创建。
- 放置建议:
Assets/LoL/Setting/YooAsset/AssetArtScannerSetting.asset
- 版本管理:若团队固定扫描规则(尺寸/格式阈值),建议提交。
ScannerSchema/*
(示例 Schema 与参数资产)
目录含义:存放扫描器的 Schema 资产与示例(如
EffectTextureSchema
)。作用:为某个扫描器提供阈值/规则参数(比如最大贴图尺寸、平台压缩格式等)。
类型:均为继承自
ScannerSchema
的 ScriptableObject。创建方式:
- 示例项目已给出样例;
- 你也可以在 Project 视图里 Create → YooAssetArt/Create XXXSchema 自定义创建。
是否必须:只在使用 AssetArt Scanner 时需要;否则可不创建/不提交。
它们从哪里来?怎么“正确生成”
AssetBundleCollectorSetting.asset
- 打开 YooAsset → AssetBundle Collector
- 如果窗口顶端提示找不到配置,点一次 Fix(或新增一个 Package 再 Save)→ 自动生成
- 以后你每次修改 Package/Group/Collector 并 Save,都会写回这份资产
AssetBundleCollectorConfig
- 在 Collector 窗口右上角点 Export 生成;Import 用于从这份备份恢复规则
AssetArtScannerSetting.asset
- 打开 YooAsset → AssetArt Scanner,在左侧添加/配置扫描器后 Save 生成
ScannerSchema/*.asset
- 右键 Create(示例提供了
Create TextureSchema
等菜单)或自定义脚本创建
- 右键 Create(示例提供了
放置与迁移建议
推荐统一放置:
Assets/XX/Setting/YooAsset/ AssetBundleCollectorSetting.asset AssetBundleCollectorConfig //(可选) AssetArtScannerSetting.asset //(可选) ScannerSchema/ //(若使用扫描器)
移动/改名后:
- Collector / Scanner 窗口若提示缺失,点击 Fix;
- 记得连同 .meta 一起移动/提交,避免 GUID 改变导致引用失效。
运行时与打包期的关系
- 以上资产只在编辑器期被 YooAsset 的 Collector/Scanner/Builder 使用;换句话说,这些 .asset/配置只在 Unity 编辑器里给 YooAsset 的窗口用,用来决定怎么打包,它们不会被游戏运行时代码读取;不会进最终包体。
- 点 Build 后,YooAsset 根据“配方”做出真正给游戏运行用的文件,包括AB包,清单,版本文件等;
- 因此:把它们放进
Resources/
或 Addressables/YooAsset 里都没有意义;别让它们误入首包。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com