Resources的序列化

当项目构建时所有名为Resources的文件夹中所有的Asset和Object都会合并到同一个序列化文件中,这个序列化文件还包含元数据和索引信息,这个索引中包含一个用于将给定Object名称转换为恰当的FileID和LocalID的序列化查找树 数据结构式平衡二叉树,其时间复杂度O(nlog(n)),因此索引加载时间随Resources文件夹内的Object数量而增长的速度呈线性增长

AssetBundle基本原理

概述:

        AssetBundle系统提供了将一个或多个文件存储到Unity能够进行索引序列化的档案格式中的方法

AssetBundle布局

       简单的说,一个AssetBundle中包含两部分:数据头和数据段

       数据头中包含一个AssetBundle的相关信息,例如标识符,压缩类型和配置文件。配置文件是一个以Object名称为键的查找表,表中的每个条目头提供了一个用于标识Object在数据段中的位置的索引

       数据段中含有序列化AssetBundle中的Asset生成的原始数据,如果指定了压缩方案LZMA所有的序列化文件包含到一个字节数组中,如果指定了为LZ4,不同的Asset字节会被单独压缩

       LZMA会序列化数据压缩成一个LZMA流,使用时需要整体解包,优点体积小,缺点是解包时间长导致加载时间长

       LZ4会生成更大的压缩文件,优点是使用时不需要整体解压。LZ4是一种基于chunk算法,加载对象是只有相应的chunk会被解压

加载AssetBundle 有5个API 这5个API会受到下面两个因素影响产生不同的行为

1,AssetBundle使用LZMA压缩还是LZ4压缩方式或没有压缩

2,进行加载的AssetBundle平台

这些API是:

  • AssetBundle.LoadFromMemory(可选择异步模式)
  • AssetBundle.LoadFromFile(可选择异步模式)
  • AssetBundle.LoadFromStream(可选择异步模式)
  • UnityWebRequest的DownloadHandlerAssetBundle
  • WWW.LoadFromCacheOrDownload (Unity 5.6以及更高版本)

AssetBundle.LoadFromMemoryAsync   不推荐这个API 从托管代码的字节数组中加载,该方法始终将托管代码中的源数据复制到连续的内存空间中,如果AssetBundle被LZMA压缩将在复制时解压AssetBundle。 这个API占用内存的峰值至少是他所处理的AssetBundle大小的两倍:一份由此API创建在本机内存中的副本和一份传递到给API的位于托管字节数组中的副本 Asset会在内存中被复制3次:托管代码中的字节数组,本地内存的副本,Asset自身占用的内存

AssetBundle.LoadFromFile 用于从本地存储加载未压缩或使用LZ4压缩的AssetBundle的高效API 这个API只会加载数据头,把其余的数据保留在磁盘上,AssetBundle中的Object会在调用了加载方法(AssetBundle.Load)或者在InstanceID被引用时按需加载 在这种情况下不需要消耗额外的内存

建议 通常情况下,应该使用AssetBundle.LoadFromFile在速度,磁盘使用和运行时内存都很高效。如果必须下载AssetBundle,建议使用UnityWedRequest制作 要确保在合适的位置调用Dispose方法 可以使用Using语句

在AssetBundle加载Asset

同步版本都比异步速度快至少块一帧

当家再多个嵌套Object的复合Asset是使用LoadAssetWithSubAssets,例如加载嵌入了动画的FBX文件,或者加载嵌入多个精灵的图集

底层加载细节:Object的加载不在主线程中执行,Object的数据会在工作线程中进行读取,unity系统中任何非线程敏感的内容都会被转移到工作线程中,Object开始并行加载,在多个工作线程对多个Object进行反序列化处理和继承,当一个Object完成加载后会回调Awake 同步的AssetBundle.Load(方法会暂停主线程)知道Object加载完成

AssetBundle依赖

在运行时,Unity提供了一个API用于加载在AssetBundle构建过程中通过AssetBundleMainfest生成的依赖信息

当一个AssetBundle的父AssetBundle中的Object引用了其他AssetBundle中的Object,前者会依赖后者 ,AssetBundle是它所包含的通过每个Object的FIleID和LocalID是被的源数据的数据源,因为Object会在InstanceID首次被加载时进行加载,而且当加载AssetBundle时Object会被分配一个InstanceID所以加载AssetBundle的顺序不重要,但是在加载Object自身之前加载它所以来的所有AssetBundle很重要。当加载了父AssetBundle后,unity不会尝试其自动加载任何字AssetBundle

unity ab合并相同文件_序列化

从AssetBundle1加载材质A之前,必须先加载AssetBundle2,但这不意味着在加载AssetBundle1之前必须先加载AssetBundle2或者从AssetBundle2中加载纹理B,只要在AssetBundle1中加载材质A之前加载AssetBundle2就足够了

AssetBundle配置表(MainFeat)