【Unity】AssetBundle的使用——打包/解包

最近参考了各位大神的资源,初步学习了Unity的资源管理模式,包括在编辑器管理(使用AssetDatabase)和在运行时管理(使用Resources和AssetBundle)。在此简单总结运行时用AssetBundle动态打包/解包资源的方法,方便自己回顾。

关于AssetBundle有很多的细节问题,在此先作个笔记,等更多的问题搞清楚了/有了新的理解,再接着补充/修改。


创建编辑器菜单项,用于打包AssetBundle

using UnityEngine;
using System.Collections;
using System.Collections.Generic; // 需要使用List集合
using UnityEditor; // 创建编辑器菜单项需要导入这个文件

public class CreateMenuItem  { // 不需要继承Mono

    [MenuItem("My MenuItem/Build AssetBundle")]
    public static void BuildBundle() 
    {   
        List<AssetBundleBuild> list = new List<AssetBundleBuild>(); // 多个资源可以打入一个包中,不确定个数时,可用List集合一个一个添加
        AssetBundleBuild b = new AssetBundleBuild();
        b.assetBundleName = "1.unity3d"; // 用于加载该资源,相当于这个资源在AssetBundleBuild中的ID,因为AssetBundleBuild中可能有多个资源
        b.assetNames = new string[] { "Assets/Resources/Images/1.jpg" }; // 这个AssetBundleBuild里包含的哪些资源
        list.Add(b);

        // 该方法不会自动生成文件夹,所以若指定的文件夹不存在,则打包失败
        BuildPipeline.BuildAssetBundles("Assets/Bundles", list.ToArray(), BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
    }
}

打包成功后,在目标文件夹下多了如下4个文件:
这里写图片描述

关于制作编辑器菜单项

  • 需要把该脚本放在Editor目录下,建议在Assets根目录下新建“Editor”文件夹。
  • 需要导入UnityEditor文件。
  • 菜单项的类不用继承MonoBehaviour。
  • 需要使用MenuItem特性。
  • 点击菜单项触发的函数是static静态的。

关于打包AssetBundle

  • assetBundleName : 该资源打入包后的名字,解包时可用该名字访问到该资源。
  • assetNames : 要被打包的资源当前的相对路径。
  • 打包函数:BuildPipeline.BuildAssetBundles()。
  • 打包函数要求传入AssetBundleBuild[]数组,因为一个AssetBundle压缩包中可以被加入多个资源,可以使用动态数组List来替代(不用指定数组长度),使用集合的Add()方法将资源一个一个加入包中。
  • 关于参数BuildAssetBundleOptions,以前常用的选项BuildAssetBundleOptions.CollectDependencies和BuildAssetBundleOptions.CompleteAssets都已过时,官方文档解释是这两种选项现在都默认会被执行。关于这个参数我没有过多的探究,这里暂时选用了BuildAssetBundleOptions.None。
  • 方法的最后一个参数BuildTarget指定打包到哪个平台下,这里我用PC测试选择BuildTarget.StandaloneWindows64。
  • 打包方法中填的目标文件夹路径如果不存在,该方法不会创建该文件夹,打包失败。
  • 这里只是简单的打包一个资源,没有涉及打包多个资源时,不同资源有共通引用别的资源的问题,学习中。

加载/解包AssetBundle

public class LoadAssetBundle : MonoBehaviour {

    void Start () {
        StartCoroutine(Load());
    }

    // 加载AssetBundle压缩包是个异步过程,需要开启协程
    IEnumerator Load()
    {
        // 步骤一:获取AssetBundle压缩包
        //  WWW www = new WWW("http://myserver/myBundle.unity3d"); // 从远端服务器下载
        //  WWW www = new WWW("File://" + Application.streamingAssetsPath + "1.unity3d"); // 手机上从本机加载
        WWW www = new WWW("File:///D:/Unity Projects/Learn Asset Manage/Assets/Bundles/1.unity3d"); // 从PC本机加载,是三个杠
        yield return www;

        AssetBundle build = www.assetBundle;
        Debug.Log(build); // 测试是否非空

        // 步骤二:解包获取资源
        /*
        // 异步加载,分帧操作
        AssetBundleRequest request = build.LoadAssetAsync("Assets/Prefabs/airplane.prefab", typeof(GameObject)); // 名字和类型是打包时确定的
        yield return request;
        GameObject go = request.asset as GameObject;
        */
        // 同步加载,速度更快,但可能会阻塞主线程
        GameObject go = build.LoadAsset<GameObject>("Assets/Prefabs/airplane.prefab");


        Instantiate(go, new Vector3(0, 0, 0), Quaternion.identity);

        // 完成后释放原始镜像文件
        www.Dispose();
    }
}

注意点:

  • 加载AssetBundle压缩包是个异步过程,需要开启协程。
  • 压缩包的获取方式有三种:从远端服务器、手机上本地加载、PC上本地加载。想要在手机上加载本地AssetBundle,需要将所需资源包存放在自创建的名为“StreamingAssets”的文件夹中,该资源才能发布到真机上。参考Streaming Assets
  • 解AssetBundle包可以使用异步或同步加载方式,前者分帧操作加载稍慢,后者加载更快但可能阻塞主线程。
  • 解压完成后可以通过www.Dispose()方法将原WWW的压缩包镜像文件释放。
posted @ 2016-07-22 00:38  霍莉雪特  阅读(6840)  评论(0编辑  收藏  举报