【Unity基础框架】YooAsset 学习(一)

YooAsset 学习记录

跟着b站视频+文档学习的

地址:https://github.com/tuyoogame/YooAsset

YooAsset 基于的原理也是来源于Unity的 AssetBundleAddressable
AssetBundle的原理及最佳实践

YooAsset简介

具体的简介项目里都有,就简单截一些了
在这里插入图片描述

1.Editor

1.1导入YooAsset

直接看文档。

总共三种,用的是这种
在这里插入图片描述
在这里插入图片描述

1.2 全局配置

在这里插入图片描述
Resources下新建 YooAsset 配置文件
在这里插入图片描述

1.3 资源配置

配置直接看文档
在这里插入图片描述

1.3.1 AutoCollectShaders

新版已经没有这个选项了。
在这里插入图片描述
ShaderVariant Collector 仍在
在这里插入图片描述

旧版:

搜集所有Group内的材质球,把它们的shader打入一个包内
在这里插入图片描述
这里设置好后打开
在这里插入图片描述
为了防止Shader资源荣誉,点击搜集变种生成
在这里插入图片描述
点击完毕后,会跳到它给我们的一个所有Shader的材质球展示界面。以及生成了 ShaderVariants 的搜集结果文件
在这里插入图片描述
然后在热更资源目录新建一个文件夹,放入这个配置文件
在这里插入图片描述
然后在YooAsset打包配置里新建一个它的收集器
在这里插入图片描述
专门为它自定义一个打包规则
在这里插入图片描述
这里返回的名称和Shader Bundle Name一致
在这里插入图片描述
最后给搜集器换成自定义的打包规则类即可
在这里插入图片描述

1.4 资源打包

在这里插入图片描述
记录一些配(详细配置请看文档,只记录了部分)

  • Build Pipeline 构建管线

    1. BuiltinBuildPipeline: 传统的内置构建管线。
    2. ScriptableBuildPipeline: 可编程构建管线。
  • Build Mode 构建模式

    1. 强制构建模式:会删除指定构建平台下的所有构建记录,重新构建所有资源包。
    2. 增量构建模式:以上一次构建结果为基础,对于发生变化的资源进行增量构建。
    3. 演练构建模式:在不生成AssetBundle文件的前提下,进行演练构建并快速生成构建报告和补丁清单。
    4. 模拟构建模式:在编辑器下配合EditorSimulateMode运行模式,来模拟真实运行的环境。
  • Output Name Style 输出的资源包文件名称样式

    1. HashName:哈希值
    2. HashName_Extension:哈希值+后缀名
    3. HashName_BundleName_Extension:资源包名+哈希值+后缀名
  • Copy Buildin File Option 首包资源文件的拷贝方式

    1. None:不拷贝任何文件
    2. ClearAndCopyAll:先清空已有文件,然后拷贝所有文件
    3. ClearAndCopyByTags:先清空已有文件,然后按照资源标签拷贝文件
    4. OnlyCopyAll:不清空已有文件,直接拷贝所有文件
    5. OnlyCopyByTags:不清空已有文件,直接按照资源标签拷贝文件

重要概念

  • 增量构建
    增量构建是在Unity的帮助下实现的一种快速打包机制。主要是利用资源构建相关的缓存文件来避免二次构建,以此来提高打包效率。
  • 强制构建
    强制构建是每次构建之前,都会清空之前构建的所有缓存文件,以此来重新构建资源包。
  • 首包资源
    在构建应用程序的时候,我们希望将某些资源打进首包里,**首包资源拷贝至StreamingAssets/BuildinFiles/目录下。**首包资源如果发生变化,也可以通过热更新来更新资源。
  • 补丁包
    无论是通过增量构建还是强制构建,在构建完成后都会生成一个以包裹版本(PackageVersion)命名的文件夹,我们把这个文件夹统称为补丁包。补丁包里包含了游戏运行需要的所有资源,我们可以无脑的将补丁包内容覆盖到CDN目录下,也可以通过编写差异分析工具,来筛选出和线上最新版本之间的差异文件,然后将差异文件上传到CDN目录里。
    在这里插入图片描述
    不勾就是增量,勾选就是重出包了。

1.4.1 自定义加密

在这里插入图片描述
在这里插入图片描述

  • Check 检查哪些文件要加密,比如配置表。路径是相对应于Assets下的(“Assets/xxx/xxx”)
    在这里插入图片描述
  • Encrypt 就是具体的加密算法了。demo里提供了一个简单的数据偏移算法。
    在这里插入图片描述

1.4.2 Buildin Tags

在这里插入图片描述
Buildin Tags 里填的是Group 的 Grouper Asset Tags。就是表示你这次想把哪些 Group 打包。

多个 Tag 用 ; 隔开。 
buildin;level;other

1.4.3 补丁清单

在这里插入图片描述

  1. AssetList
    所有通过Grouper搜集器搜到的通过代码加载的资源。
    在这里插入图片描述

    • AssetPath Asset下的相对路径
    • BundleID 主BundleID
    • DependIDs 以来的BundleID们
  2. BundleList
    根据YooAsset配置生成的所有Bundle了

    上面的BundleID指的就是这个列表下的Bundle
    在这里插入图片描述

    • Hash 它的hash值
    • CRC 验证完整性
    • SizeBytes 大小
    • Tags 包含了Grouper Asset Tags 和 搜集器上填的 tag
    • Flag 一些附加数据全部存在这里(= =没搞懂)
  3. YooAsset的不同之处

    1. 记录AssetPath对应的资源对象依赖了哪些Bundle。
    2. 记录 AssetPath对应的资源对象的Bundle 依赖了哪些 Bundle

而大部分其他的框架是用 2. 的方式。

而 2. 的方式有个问题。比如有 A、B、C、D 三个 Bundle,对象 X 在 A 、C Bundle 里

X in A Depend A、C
A depend B
B depend C、D

方法 2.
会导入 ABCD
X -> A -> B -> C、D  result ABCD

方法 1. 
直接导入A、C即可。
因为经过计算,这里的依赖是展开的,不是树形,不需要再查每个Bundle下层的依赖了
X in A Depend A、C
X -> A ,X -> C	result A、C

1.5 资源部署

在这里插入图片描述
增量更新直接替换就可以了。记得用类似Beyonce Compare比对一线,不用上传没改变的文件。

1.6 构建报告

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个构建报告,在生成的文件下面都有。导入的就是这个东西。

AssetView

在这里插入图片描述
Grouper里搜集的,所有通过代码加载的资源对象。

  • Size 大小
  • Main Bundle 位于哪个Bundle里

在这里插入图片描述
原生数据其实不是AB包的格式。并且每份都有一个资源包。

BundleView

在这里插入图片描述
以Bundle视角的视图。下面可以看到这个Bundle里可以用代码加载的资源列表。

2.代码部分

这部分代码具体请看文档。仅会贴出部分

2.1 初始化

2.1.1初始化资源系统

// 初始化资源系统
YooAssets.Initialize();

// 创建默认的资源包
var package = YooAssets.CreateAssetsPackage("DefaultPackage");

// 设置该资源包为默认的资源包,可以使用YooAssets相关加载接口加载该资源包内容。
YooAssets.SetDefaultAssetsPackage(package);
资源系统的运行模式支持三种:编辑器模拟模式,单机运行模式,联机运行模式。
编辑器模拟模式
	在编辑器下,不需要构建资源包,来模拟运行游戏。
	
	注意:该模式只在编辑器下起效
	
	private IEnumerator InitializeYooAsset()
	{
	    var initParameters = new EditorSimulateModeParameters();
	    initParameters.SimulatePatchManifestPath = EditorSimulateModeHelper.SimulateBuild("DefaultPackage");
	    yield return defaultPackage.InitializeAsync(initParameters);
	}
联机运行模式

对于需要热更新资源的游戏,可以使用联机运行模式,该模式下初始化参数会很多。

注意:该模式需要构建资源包

  • DecryptionServices : 如果资源包在构建的时候有加密,需要提供实现IDecryptionServices接口的实例类。
  • QueryServices:内置资源查询服务接口。
  • DefaultHostServer : 默认的资源服务器IP地址。
  • FallbackHostServer : 备用的资源服务器IP地址。

如果只有一个CDN地址那就都填一样的

	private IEnumerator InitializeYooAsset()
	{
	    var initParameters = new HostPlayModeParameters();
	    initParameters.QueryServices = new QueryStreamingAssetsFileServices();
	    initParameters.DefaultHostServer = "http://127.0.0.1/CDN1/Android/v1.0";
	    initParameters.FallbackHostServer = "http://127.0.0.1/CDN2/Android/v1.0";
	    yield return defaultPackage.InitializeAsync(initParameters);
	}
	
	// 内置文件查询服务类
	private class QueryStreamingAssetsFileServices : IQueryServices
	{
	    public bool QueryStreamingAssets(string fileName)
	    {
	        // 注意:使用了BetterStreamingAssets插件,使用前需要初始化该插件!
	        string buildinFolderName = YooAssets.GetStreamingAssetBuildinFolderName();
	        return BetterStreamingAssets.FileExists($"{buildinFolderName}/{fileName}");
	    }
	}

老版本和新版本差异有点大啊在这里插入图片描述

源代码解析
编辑器模拟模式

每次启动调用EditorSimulateModeHelper.SimulateBuild()方法,都会在底层执行一次模拟构建(Simulate Build)。

如果参与构建的资源对象数量级很大的话则会有卡顿现象,可以通过直接指定已有的清单路径来避免每次都重复执行模拟构建。

单机运行模式

在初始化的时候,会直接读取内置清单文件(StreamingAssets文件夹里的文件),最后根据加载的清单去验证沙盒里缓存的文件。

联机运行模式

在初始化的时候,会优先从沙盒里加载清单,如果沙盒里不存在,则会尝试加载内置清单并将其拷贝到沙盒里。最后根据加载的清单去验证沙盒里缓存的文件。

注意:如果沙盒清单和内置清单都不存在,初始化也会被判定为成功!

2.2 资源更新

在这里插入图片描述
demo里实现了一个状态机,咱们可以直接拿来用。

文档和视频内容有差异,这里只好直接用视频的文档截图了

在这里插入图片描述
也可以自己写HTTP逻辑来访问。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述
这里的 tags 就是对于的 Grouper Asset Tags ,表示你想下载那个 Grouper。

不太理解这么做的原因= =。

2.2.1 路径

内置文件

在这里插入图片描述
重新强制出包的时候,把生成的内容放到如图目录下。

沙盒

在这里插入图片描述在这里插入图片描述

在PC上的地址和Asset同级,应该就是可写目录了。也就是热更新文件的存放位置。

2.2.2 下载器

在这里插入图片描述
补丁下载目前只有两种,传入单/多 个Grouper Asset Tag 。

这样可以实现按需下载,比如我可以在进入关卡的时候再下载这个关卡的资源(进入关卡Loading的时候下载)。

3.补充部分

3.1 Sample 改造

我直接拿Sample里的Sapce Shooter的热更流程来改了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
大致保留这些就行了。

还有提供的UniFramework系类的挺好用的,要是不想自己写事件系统之类的,可以直接拿来用。
在这里插入图片描述

3.2 UniTask接入

4.AssetBundle 学习笔记(简略)

Unity学习—AssetBundle

以下内容为此博客的笔记。

详细介绍请看博客,这里只记简略。

4.1 AssetBundle 作用

  • AssetBundle 是外部资产的集合,可独立于 Unity 构建过程外,是 Unity 更新非代码内容的主要工具;
  • AssetBundle 使开发者可以提交更小的应用包,最小化运行时内存压力,使终端可以选择性加载优化内容

4.2AssetBundle 组成

AssetBundle 主要由两部分组成:文件头和数据段

文件头包含了id、压缩类型、索引清单,该索引清单是与 Resources 相同的记录了序列化文件中的字节偏移量的查找表。对于大部分平台该表为平衡搜索树,对 Windows 和 OSX 系列(包括 iOS)则为红黑树,随着 AssetBundle 中对象的增加,构造清单所需时间的增长速度将超过线形增长速度

数据段包含了 Asset 经过序列化的原始数据,数据还可选择是否压缩,

  • 若使用 LZMA 压缩,则将所有 Asset 的字节数组整体压缩;
  • 若使用 LZ4 压缩,则将每个 Asset 单独压缩;
  • 若不压缩,则数据保持原始字节流

4.3AssetBundle 加载

有四种不同的 API 用于加载 AssetBundle,但每个 API 的行为随压缩算法和平台而不同

  • AssetBundle.LoadFromMemoryAsync
  • AssetBundle.LoadFromFile
    该方法可高效地从硬盘加载未压缩或 LZ4 压缩的 Assetbundle,加载 LZMA 压缩包时会先解压再加载到内存
  • WWW.LoadfromCacheOrDownload(5.6 及以前版本)旧方法,已抛弃
  • UnityWebRequestAssetBundle (5.3 及以后版本)

官方推荐尽量使用 AssetBundle.LoadFromFile,该 API 在速度、磁盘使用和运行时内存使用方面都最高效;需要下载则使用 UnityWebRequest

注:Web平台都用 UnityWebRequest 来加载,web平台没有本地存储数据

4.4 AssetBundle Asset 加载

同步异步加载 Asset 一共有六种 API 可使用

  • LoadAssets (LoadAssetsAsync)

  • LoadAssetWithSubAssets (LoadAssetWithSubAssetsAsync)
    适合需要加载的对象内嵌了其他对象的情况,若加载对象均来自于一个 Asset 且包中有许多其他无关对象,则使用该 API

  • LoadAllAsset (LoadAllAssetAsync)
    其他情况均用LoadAsset (LoadAssetAsync)

4.5 AssetBundle 依赖

当一个对象所在的 AssetBundle 被加载时,该对象就被分配了一个唯一的有效实例 ID。Unity 不会自动加载子 AssetBundle。就是不会加载你的依赖,咱们必须自己处理加载依赖的AssetBundle。

在构建 AssetBundle 时,Unity 创建一个包含每一个 AssetBundle 依赖信息的类型为 AssetBundleManifest 的序列化对象,该文件存在一个与其他 AssetBundle 在同一打包路径下的单独的 AssetBundle 中,且与父层文件夹名相同。

有两种 API 查询依赖

  • AssetBundleManifest.GetAllDependencies 获取 AssetBundle 的所有依赖层级
  • AssetBundleManifest.GetDirectDependencies 获取 AssetBundle 直接依赖

因该 API 会生成字符串数组,所以应尽量少用,且避免性能高峰时使用

官方建议
大部分场合下,在进入性能需求高的场景前,尽可能多地加载对象,尤其对于移动平台这种,访问本地存储慢,加载卸载对象引起内存流失会触发垃圾回收的平台

4.6 AssetBundle 使用

这个问题和资源卸载有关。

不适当地卸载 AssetBundle 会导致对象缺失或者在内存中重复。

调用AssetBundle.Unload可卸载 AssetBundle 的头信息,传入参数 true 或 false 决定是否同时卸载该包下所有已加载对象。

  1. 由此诞生一个问题,当卸载了 AssetBundle 未卸载已加载对象时,此时这些对象与 AssetBundle 便失去关联了,重新加载 AssetBundle 并重新加载同一对象时,只会产生一个新的关联对象,而旧对象则无法使用AssetBundle.Unload卸载了,这就导致了内存中同时存在两个一样的对象。
    在这里插入图片描述

  2. 另外还可能出现的问题是,在 AssetBundle 卸载之后加载 AssetBundle 中的对象时,会出现对象缺失的问题。出现该问题大部分原因为 Unity 丢失又重新获得对图形上下文的控制,如移动设备 App 挂起,PC 锁定等场景

4.7 AssetBundle 发布

在这里插入图片描述
也就是说,AssetBundle.LoadFromFile只能在无压缩的apk获取AssetBundle???

4.8 自定义下载器

这部分看博客

4.9 Asset 分包策略

  • 逻辑实体分包
  • 对象类型分包
  • 并发内容分包
    在这里插入图片描述
    AssetBundle变体是什么意思?

4.10 常见问题

只贴出原因,解决方案请看博客。或者这部分直接到博客里看

4.10.1 资产重复

若有一个未分配资产被多个不同 AssetBundle 中的已分配资产引用,则在构建 AssetBundle 时,该引用对象会被拷贝到每个 AssetBundle 中,造成空间和内存浪费

4.10.2 精灵图集重复

任何自动生成的图集会被分配到其包含精灵所在的 AssetBundle,若精灵对象被分配到多个包,则图集会被复制,因此需确保同一图集的精灵对象被分配到同一 AssetBundle 中

4.10.3 Android 纹理

由于 Android 生态的碎片化,经常需要使用不同格式压缩纹理。

为了适配支持不同纹理格式的android机器。使用AssetBundle变体

5.AssetBundle 变体

AssetBundle Variants 的主要作用在于使 AssetBundle 随运行时环境调整其内容配置。

AssetBundle Variants 使不同 AssetBundle 中的不同对对象在加载时公用一个实例 ID,使其看起来为同一个对象。

个人觉得多渠道多语言也可以用这个。

6.其他

在这里插入图片描述

5.问题&解答

Q:自己使用的时候,收集器里只有原生类型的文件,然后报错“No AssetBundle has been set for this build.”

A:
意思就是你的AssetBundle根本没东西啊,没东西用什么AssetBundle。
然后添加了一个Scene到收集器里,就不报错了
。。。服了,原生类型不配算资源呗?