Unity学习日记:AssetBundle工作流程之资源的打包与加载
发表于2018-02-12
在很多类型游戏的制作过程中,开发者都会考虑一个非常重要的问题,即如何在游戏运行过程中对资源进行动态的下载和加载。为此,Unity引擎引入了AssetBundle这一技术来满足开发者的上述需求,一方面,开发者可以通过AssetBundle将游戏中所需要的各类资源打包压缩并上传到网络服务器上;另一方面,在运行时游戏可以从服务器上下载该资源,从而实现资源的动态加载。ok,要实现动态的下载和加载资源,第一步就是先要打包资源。unity使用BuildPipeline.BuildAssetBundles来打包资源。
打包方法一:首先,创建三个Prefab来作为我们想要打包的资源,并创建两个材质球为Prefab上色。

然后在Assets下创建一个名为Editor的文件夹(此文件夹名不能更改,否则打包失败),并在其中创建打包所用的脚本,命名为AssetBundlesBuild(可随意命名)。

编辑脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor;//必须先引用UnityEditor public class AssetBundlesBuild : MonoBehaviour { //在菜单栏中添加一个名为AssetBundles的菜单(可随意命名),并在其下添加一个命名为Build AssetBundles的选项(随意命名) [MenuItem("资源包/创建资源包")] //创建一个静态方法用来执行打包操作(方法名随意) static void aaa() { //创建一个AssetBundleBuild的类型的数组,因此例中要打包两个资源包,故数组容量为2。 //这个数组其实是定义了你要打包的资源文件和资源包之间的关系,也就是说将Assets文件夹下的哪些资源文件打包到哪些资源包里面。 AssetBundleBuild[] buildmap = new AssetBundleBuild[2]; //将要打包的第一个资源包的名称命名为ZiYuanBao1 buildmap[0].assetBundleName = "ZiYuanBao1"; //将要打包的第二个资源包的名称命名为ZiYuanBao2 buildmap[1].assetBundleName = "ZiYuanBao2"; //创建一个字符串数组用来指明ZiYuanBao1想要打包的资源文件及其位置,打包文件数既是数组容量 string[] ziyuan = new string[2]; //将Prefab1和Prefab2在Assets文件夹下的目录及其名称和文件类型作为字符串赋给字符串数组 ziyuan[0] = "Assets/Prefab1.Prefab"; ziyuan[1] = "Assets/Prefab2.Prefab"; //指明ZiYuanBao1想要打包的资源文件 buildmap[0].assetNames = ziyuan; //创建字符串数组ziyuan2用来指明ZiYuanBao2想要打包的资源文件及其位置,打包文件数既是数组容量 string[] ziyuan2 = new string[1]; //将Prefab3在Assets文件夹下的目录及其名称和文件类型作为字符串赋给字符串数组 ziyuan2[0] = "Assets/Prefab3.Prefab"; //指明ZiYuanBao2想要打包的资源文件 buildmap[1].assetNames = ziyuan2; //完成打包,输出路径为Assets下的StreamingAssets文件夹(可随意命名,但必须确定存在该文件夹) //此行意为:在不对资源包设置任何特殊选项的情况下按照buildmap所指定的文件关系进行打包,资源包目标平台是StandaloneWindows,输出路径是Assets/StreamingAssets BuildPipeline.BuildAssetBundles("Assets/StreamingAssets",buildmap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); //刷新资源路径,避免生成的文件不显示 AssetDatabase.Refresh (); }}
可以看到脚本编译完成后,菜单栏多出了一个选项。

最后执行打包动作,打包完成,指定文件夹下出现了相关资源包文件:

打包方法二:在方法一中,我们以编写代码的方式为资源文件和资源包指明了打包关系,为了提高效率,unity还提供了另一种方法如下。
首先,点击想要打包的资源文件,在Inspector视图中设置想要包含此资源文件的资源包名称。如图。

此处,我们将Prefab1和Prefab2的Assetbundle设置为bundle1,将Prefab3的Assetbundle设置为bundle2,既将Prefab1和Prefab2打包在资源包bundle1里面,将Prefab3打包在资源包bundle2里面。
然后同样是在Assets文件夹下面创建一个名为Editor的文件夹(此文件夹名不能更改,否则打包失败),并在其中创建打包所用的脚本,命名为AssetBundlesBuild(可随意命名),因为之前已经创建过,故不再次进行创建了。打开脚本,编辑。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class AssetBundlesBuild : MonoBehaviour { //在菜单栏中添加一个名为AssetBundles的菜单(可随意命名),并在其下添加一个命名为Build AssetBundles的选项(随意命名) [MenuItem("AssetBundles/Build AssetBundles")] //创建一个静态方法用来执行打包操作(方法名随意) static void aaa() { //完成打包,输出路径为Assets下的StreamingAssets文件夹(可随意命名,但必须确定存在该文件夹) //此行意为:在不对资源包设置任何特殊选项的情况下按照在unity中Inspector视图中所指定的文件关系进行打包,资源包目标平台是StandaloneWindows,输出路径是Assets/StreamingAssets BuildPipeline.BuildAssetBundles("Assets/StreamingAssets", BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows); //刷新资源路径,避免生成的文件不显示 AssetDatabase.Refresh (); }}
最后执行打包动作,打包完成,指定文件夹下出现了相关资源包文件:

AssetBundle使用的增量式打包仅重新打包发生变化的资源包,当资源文件或者typetree发生变化时才会重新打包。
将之前所生成的Ziyuanbao1和ziyuanbao2及其Manifest文件删除。并且把最开始生成的两个材质球打包成bundle3。

新建脚本,编辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DownloadAssetBundle : MonoBehaviour { // Use this for initialization IEnumerator Start () { WWW w1 = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/StreamingAssets/StreamingAssets", 0); yield return w1; if (w1.error != null) { Debug.Log(w1.error); } else { AssetBundle abManifest = w1.assetBundle; yield return abManifest; AssetBundleManifest manifest = abManifest.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); string[] depend = manifest.GetAllDependencies("bundle1"); AssetBundle[] depend_ab = new AssetBundle[depend.Length]; for (int i = 0; i < depend.Length; i++) { WWW w = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/StreamingAssets/" + depend[i],0); yield return w; depend_ab[i] = w.assetBundle; yield return depend_ab; } WWW w2 = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/StreamingAssets/bundle1", 0); yield return w2; AssetBundle Bundle1 = w2.assetBundle; AssetBundleRequest request= Bundle1.LoadAssetAsync("Prefab1");//异步加载 yield return request; GameObject obj = (GameObject)request.asset; Instantiate(obj, Vector3.zero, Quaternion.identity); } } }
编辑完成后,将脚本挂载到Camera上,运行之后会在场景内见到被加载上来的Prefab1。

关于下载及加载Assetbundle的详细步骤解析:http://gad.qq.com/article/detail/40879
如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引