赞
踩
系统所做的事情:
1.打包(分析依赖,增量打包)
2.加载(依赖关系加载,多版本支持)
3.卸载(自动卸载无引用资源)
1.先说一下打包规则
为了打包方便,需要定制一套打包规则。
这里的规则:
a.基于文件夹的策略打包
b.打包规则分为 SelfName(资源自身名字为包名)
c.打包规则分为 ForderName(资源所在文件夹为包名)
具体策略:
如图所示:
预制体放在一个文件夹,采用SelfName。
精灵图片放在一个文件夹,采用SelfName。
声音放在一个文件夹,采用FolderName。
(仅仅只是演示,具体策略需要根据项目不同的需求来制定)
(把登陆之前打成一个group,登陆后释放;把每个活动打成一个group等等)
那么上图是什么呢?
就是一个打包编辑器,可以配置需要导出的资源。
本质上就是一个ScriptableObject,通过扩展编辑器开发个UI界面。
定义一个AssetBundleConfig:
创建一个
AssetBundleConfig config= ScriptableObject.CreateInstance<AssetBundleConfig> ();
AssetDatabase.CreateAsset (config, path);
创建后如图所示:
规则定完后,开始打包。
2.打包逻辑
打包逻辑主要分五步:
**a.Begin:**准备阶段,负责读取上一次保存的缓存文件。
上图为缓存文件,第一行是版本号。
然后是资源路径,资源文件Hash值,资源所在包Hash值,依赖数量,如果有的话,下面还有包的hash值。
Hash的用处:
1.文件Hash:判断这个资源是否需要增量打包,通过读取文件的byte[]数组获取。
2.包Hash:判断这个包是否需要热更,通过打包后的AssetBundleManifest文件获取。
**b.LoadAssetTargets:**加载所有的资源,构造AssetTarget对象
为什么要加载资源?
分析依赖
为什么5.x还要分析,不是4.x的时候才要分析吗?
1.为了构建自己的name-assetPath数据表,在编辑器下无需打包就能加载资源。
2.分析是否包含冗余资源。
假如说:美术偷偷传了一个材质的文件夹,他不会配到打包配置里面,就有很多prefab是依赖这个资源的。所以很多包都会包含这个资源,就会造成资源的冗余。如果事先分析,发现这种情况,就可以把这个资源,单独导出包,让其他的资源依赖这个包就可以了。
并且只需要设置一个包名,因为5.x已经帮我们做了依赖管理:如果引用的资源是单独的包,那就添加一个依赖项;如果不是,那就把这个资源包含在自己的包内。
那打包的时候设置一下这个材质不就行了吗?
这只是一种容错的方法,有些情况是不可预想的。好的团队按照规则固然重要,但是写工具要从底层处理问题,而不是依赖认为的策略去解决问题。
AssetTarget 对象是啥?
如上图,记录了:
文件信息,对应的资源,以及资源的路径、被设置的包名、当前的资源名,
以及导出规则、hash值、缓存信息、我依赖的资源、以及依赖我的资源。
作用:针对单个资源管理
1.包名与资源路径,在最后Build的时候,需要构建AssetBundleBuild
2.asset为什么要加载进来?通过EditorUtility.CollectDependencies(asset)做依赖查询
(但不是必须的,因为各种组件都会被列出来。可以无需加载asset,直接通过 AssetDatabase.GetDependencies(path),同样会获取到依赖信息,且是Gameobjec级别的。)
3.AssetCacheInfo就是文件Build之后的,缓存信息,下一次增量时会根据此比较。
4.依赖我的集合,用来做冗余剔除,如果数量超过1,就需要单独导出包。
5.ExportRule导出规则,就是之前的SelfName、FolderName,为什么还会No呢?
如果这个资源没有设置过需要导出,且只有一个包依赖次资源,Unity会把这个资源打入到这个包内,而无需导出。
**c.Analyze:**分析依赖,剔除冗余
1.开始分析,首先要获取上次的Build后的缓存信息。
如果有,并且本次资源的Hash值和之前缓存的Hash值不一样,那就需要重新导出。
如果没有,或者是Hash值一样,那就不需要重新导出。
会设置 isFileChanged 这个字段,最后导出时会判断。
2.通过AssetDatabase.GetDependencies获取依赖信息,把所有的依赖也构建成AssetTarget进行分析。再把这个资源添加到我依赖的资源中,对这个资源添加依赖它的资源,方便后期做冗余剔除。
5.当所有的资源都分析过后。
6.对依赖我的资源进行判断,如果超过2个,就需要单独导出,设置包名。
**d.Export:**导出
导出的过程,就是Buildpipeline.BuildAssetBundles
通过构建AssetBUndleBuild[]数组来构建。而不是直接设置资源的包名。
好处就是如果是git或者svn项目,设置资源的包名就会导致meta文件变化非常不方便多人协作开发。
坏处就是不能直观的看到。
并且采用ChunkBaseCompression的选项,可以加载时实时解压(速度快,官方推荐)。
**e.End:**结束,保存信息
导出完成后,通过加载AssetBundleManifest,获取每一个包的Hash值。
再构建依赖关系表,大概的格式就是:(开发模式采用文本格式,发布模式采用二进制)
结构:
assetPath:用于Editor下加载。
bundleName:记录资源对应的包名。
assetName:记录包内资源名
hash:包的hash值
depCount:依赖数量(如果有,会记录对应数量的依赖的包名,方便依赖加载)
最后一步,就是删除无用的AB。也就是上一次打包存在的,本次打包不存在了。
把本次导出的构建成HashSet,读取打包目录下的所有文件,添加到HashSet。如果添加成功了,就代表本次没有,那就需要删除这个包以及对应生成的manifest文件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。