通过之前的介绍,今天我们就进入资源包初级阶段的最后一部分的学习--如何利用Dependency来给你的Asset Bundle来减肥吧!


        从之前的各篇学习,小生已经学会了如何使用下载以及如何把下载后的文件保存在客户端程序中的缓存中,接下来小生发现了一个问题,简单的说就是如果资源包过多外加总体容量很大的话,有没有一种方法来给现有的资源包减肥呢。小生看了一些相关的介绍,得出来的结论就是合理根据资源包的结构来抽出公共部分做出公共部分的资源包,这样可以在一定程度上介绍资源包大小。


        实现上面所说的做法就是利用Asset Bundle打包方法中的Dependency的方式去打包成功资源包,外加在读取的时候要先加载公共的部分然后再读入自己的那部分从而实现。废话不说,各位客官请看代码。



using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEditor;

public class AssetBundleBuild : Editor
{
	//CollectDependencies : get dependency file of main assets and put the relate property in asset bundle
	//DeterministicAssetBundle : Make a unique id for asset bundle file
	//CompleteAssets : include all assets of a package ? 
	static UnityEditor.BuildAssetBundleOptions buildOptions = BuildAssetBundleOptions.CollectDependencies;
	
    [@MenuItem("Assets/Build Asset Bundle with dependency")]
	static void build1()
	{
		String targetPath = Application.dataPath + "/AssetBundle/Dependency/";
		String targetPath1 = "";
		String targetPath2 = "";
		String targetPath3 = "";

		//-----push the share asset to build asset bundle queue------//
		BuildPipeline.PushAssetDependencies();
		UnityEngine.Object shareAseet = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/AssetBundle/Material/share.mat");
		targetPath1 = targetPath + shareAseet.name + ".unity3d";
		BuildPipeline.BuildAssetBundle(shareAseet, null, targetPath1, buildOptions);
		//-----build the share asset to asset bundle------//

		//-----becase in include the share asset, so should put the prefab into the dependency queue-----//
		BuildPipeline.PushAssetDependencies();
		UnityEngine.Object ballPre = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/AssetBundle/Prefabs/Ball.prefab");
		targetPath2 = targetPath + ballPre.name + ".unity3d";
		BuildPipeline.BuildAssetBundle(ballPre, null, targetPath2, buildOptions);
		BuildPipeline.PopAssetDependencies();
		//-----Build the perfab to asset bundle and pop it from dependency queue------//

		//-----becase in include the share asset, so should put the prefab into the dependency queue-----//
		BuildPipeline.PushAssetDependencies();
		UnityEngine.Object capsulePre = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/AssetBundle/Prefabs/Capsule.prefab");
		targetPath3 = targetPath + capsulePre.name + ".unity3d";
		BuildPipeline.BuildAssetBundle(capsulePre, null, targetPath3, buildOptions);
		BuildPipeline.PopAssetDependencies();
		//-----Build the perfab to asset bundle and pop it from dependency queue------//

		//finall, pop the share asset from dependency queue of asset bundle process
		BuildPipeline.PopAssetDependencies();

		AssetDatabase.Refresh();
	}
}



BuildPipeline.PushAssetDependencies(), 一个是BuildPipeline.PopAssetDependencies。在制作依赖的时候,需要一压一弹的这两个动作。先说下上面代码的主要的业务,制作一个share的资源包(这个包里面存了关于下面Ball和Capsule的公用材质),然后制作Ball和Capsule的资源包的时候直接和share的这个资源进行依赖处理打包。


   


    再说下这么打包后的成果。这个材质中小生就是包涵了一个psd的图像文件,然后两个prefab就是引用的同一个材质。如果不利用这个push和pop方法单独给两个prefab打包的话也是可以的,但是在文件的大小上就会出现打包出来的这两个Asset Bundle文件里面都包含了这个psd的材质,这样的话每个文件大小60KB左右,但是使用这个依赖的方式的话,这样打包出来的含有本来要打包的两个文件外,还包含了share的Asset Bundle文件。文件大小是share的部分是60KB,而prefab的两个文件大小骤减到1KB左右的大小。这样把公共的图片部分抽出来然后单独打个包的方法节省一半的空间。可见用好依赖来进行打包的话,很多时候能产生意想不到的效果。




    接下来我们再来说说读取这种共享资源包的方法。看了官方的文档以及小生自己本地测试没问题后总结出来,读取这样依赖资源的时候,需要先把共享资源的资源包下载下来,然后再去下载对应的资源包。这个时候再Instantiate就可以正常加载了。小生也尝试过不去加载公共部分直接加载需要的包的时候会产生什么问题,结果就是依赖挂接不上,导致Game Object是能被建立出来,但是关联的材质读取不出来,Game Object就变成了一个粉色无任何关联材质的对象了。




    至此,Asset Bundle的初级探索,小生也对Asset Bundle的加载有了一个总体的了解了。