一个聪明的Assetbundle打包系统
*自动分析依赖关系,避免资源重复打包
*自动化的打包粒度管理
*支持导出dot文件,利用graphviz查看资源的依赖关系和AssetBundle包的依赖关系
为什么我打的AssetBundle包会发生资源重复(Asset Duplication)?
Objects that are explicitly assigned to an AssetBundle will only be built into that AssetBundle. An Object is “explicitly assigned” when that Object’s AssetImporter has its assetBundleName property set to a non-empty string.
Any Object that is not explicitly assigned in an AssetBundle will be included in all AssetBundles that contain 1 or more Objects that >reference the untagged Object.
资源明确设置assetBundleName的,一定会被打到那个指定名字的AssetBundle中 没有设置assetBundleName的,会被包含在所有AssetBundle中,从而发生资源重复
被多个其他资源引用的资源,需要单独打包(设置assetBundleName)
让我们先看看其他解决办法
Unity提供的AssetBundleManager
SmartBundleBuilder的解决方法
SmartBundleBuilder提供了自动分析依赖关系功能,能识别被多次依赖的资源,为它们指定AssetBundleName,从而避免了资源重复的发生
SmartBundleBuilder是如何实现分析依赖关系的?
SmartBundleBuilder利用Editor中的EditorUtility.CollectDependencies方法,对每一个需要打包的资源进行依赖关系分析,并生成一个有向图来保存这些资源的依赖关系
图的顶点表示一个资源文件,边表示一个资源对另一个资源的依赖关系,A->B,表示A被B依赖,这条边对A来说是出度(Out-degree),对B来说是入度
如果一个Asset节点的出度大于1,说明该节点被多个资源依赖,可能需要单独打包
SmartBundleBuilder主要分为个阶段
资源依赖关系分析阶段 1.使用EditorUtility.CollectDependencies方法,对被分析的资源的依赖关系生成有向图 2.删除重复的依赖关系
资源合并阶段
导出阶段
这个阶段使用EditorUtility.CollectDependencies方法,对被分析的资源的依赖关系生成有向图 如图所示
可以看到T0.png->Aura03_Red_cube.prefab,T0.png->Aura03_Red.mat形成了2个依赖,按照出度大于1就要被打包的原则,T0.png需要被单独打包
假设我们只需要导出Aura03_Red_cube.prefab这一个AssetBundle,从打包粒度上考虑,T0.png的需要单独导出会显得粒度太细。将T0.png,Aura03_Red.mat,Aura03_Red_cube.prefab合在一起打成一个包是合理的。
虽然T0.png的出度大于2,但是2个出度最终都指向了Aura03_Red_cube.prefab(直接和间接的),所以T0.png->Aura03_Red_cube.prefab的依赖可以被认为是重复的,需要被删除。
我们可以利用有向图的Transitive reduction算法,保持到达度是一致的前提下对图进行简化。 简化后的依赖关系如图所示
这个阶段将会对没有必要单独打包的资源进行合并,避免打包粒度过细。算法如下:
如果资源A只被资源B依赖,即A只有一个出度,那就将A与B进行合并,同时将A的入度合入新的组(即AB组)
再来看一个复杂的例子,包含分析阶段和合并阶段
1.我们获得了一个资源依赖关系的有向图 2.简化重复的依赖关系 3.合并迭代一次 4.合并迭代二次 5.再无可合并的资源组,合并结束