AssetBundle

AssetBundle

设置资源AB

基本上unity所包含的资源文件,除了脚本文件都可以设置成ab资源。
enter description here

生成AB资产

生成AB有两种方式

  • 自定义打包
  • AssetBundles-Browser-master插件
  1. 预览AB

这里使用插件打包,对于目前所有ab资源一目了然,如有ab设置错误也会有错误提示,我们已经设置好ab资源用它打开如图
enter description here

正是因为unity支持‘/’来分层,所以我们用文件层次来设置ab名称enter description here
才使得对应ab包层级目录结构清晰明确
2. 打包设置

enter description here
enter description here

根据当前ab资源选择不同压缩模式比较

压缩模式 UnCompression LZ4 LZMA
Andriod平台大小 325kb 160kb 119kb
  • LZ4 解压读取速度快(推荐)
  • LZMA 压缩率高,文件占用空间小,解压比较慢

获取AB加载

大致流程图示

下面示例从服务器中获取 tom ab资源一系列流程

要测试在服务中的ab资源

enter description here
enter description here

测试代码

1.连接服务器,获取主依赖

调用入口

StartCoroutine(GetDepends(host, "AB_Andriod_LZ4"));

具体实现

/// <summary>
    /// 服务器地址
    /// </summary>
    string host = @"https://ab-test-1258795305.cos.ap-shanghai.myqcloud.com/";

    /// <summary>
    /// ab-依赖
    /// </summary>
    public Dictionary<string/*ab path*/, AB_DATA> dic_AB = new Dictionary<string, AB_DATA>();

    /// <summary>
    /// 获取主依赖,本地存储依赖关系,下载全部ab
    /// </summary>
    /// <param name="host_path">服务器根地址</param>
    /// <param name="dir_name">服务器下ab根文件名,以及主ab文件名称</param>
    /// <returns></returns>
    IEnumerator GetDepends(string host_path, string dir_name)
    {
        dic_AB.Clear();

        //目录跟路径
        string root_path = host_path + "/" + dir_name;

        //获取主ab,拿到manifest获取依赖关系
        AssetBundleManifest assetBundleManifestServer = null;  //服务器 总的依赖关系    
        UnityWebRequest ServerManifestWWW = UnityWebRequestAssetBundle.GetAssetBundle(root_path + "/" + dir_name);
        Debug.Log("HTTP : " + ServerManifestWWW.url.ToString());
        yield return ServerManifestWWW.SendWebRequest();
        assetBundleManifestServer = (AssetBundleManifest)DownloadHandlerAssetBundle.GetContent(ServerManifestWWW).LoadAsset("AssetBundleManifest");


        //存储各依赖关系
        string[] depends_name = assetBundleManifestServer.GetAllAssetBundles();
        for (int i = 0; i < depends_name.Length; i++)
        {
            AB_DATA ab_data = new AB_DATA();
            ab_data.name = depends_name[i];
            
            UnityWebRequest target_uwq = UnityWebRequestAssetBundle.GetAssetBundle(Path.Combine(root_path, ab_data.name));
            yield return target_uwq.SendWebRequest();
            if (target_uwq.isDone)
            {
                //下载ab到本地
                StartCoroutine(DownLoadAssetBundelAbdSave(Path.Combine(root_path, ab_data.name)));
                //depends
                var depends = assetBundleManifestServer.GetAllDependencies(ab_data.name);
                ab_data.depends_name = new string[depends.Length];
                for (int j = 0; j < depends.Length; j++)
                {
                    ab_data.depends_name[j] = depends[j];
                }
                dic_AB.Add(depends_name[i], ab_data);
            }

        }
    }

2.缓存已下载的ab资源

  /// <summary>
    /// 下载AB文件并保存到本地
    /// </summary>
    /// <returns></returns>
    IEnumerator DownLoadAssetBundelAbdSave(string url)
    {
        WWW www = new WWW(url);
        yield return www;
        if (www.isDone)
        {
            //表示资源下载完毕使用IO技术把www对象存储到本地
            SaveAssetBundle(Path.GetFileName(url), www.bytes, www.bytes.Length);

        }
    }
    /// <summary>
    /// 存储AB文件到本地
    /// </summary>
    private void SaveAssetBundle(string fileName, byte[] bytes, int count)
    {
        string dir_path = Application.persistentDataPath + "/" + fileName;

        Debug.Log("存储路径 : " + dir_path);
        Stream sw = null;
        FileInfo fileInfo = new FileInfo(dir_path);
        sw = fileInfo.Create();
        sw.Write(bytes, 0, count);
        sw.Flush();
        sw.Close();
        sw.Dispose();
        Debug.Log(fileName + "下载并存储完成");
    }

3.从本地磁盘读取ab并实例化

调用入口

 private void LoadStream_OnClick()
    {
        //设置要加载的目标物体名
        string ab_name = "tom.prefab";
        
        string dir_path = Application.persistentDataPath + "/" + ab_name;
        //从已缓存的字节文件中加载tom
        StartCoroutine(LoadABFormStream(dir_path));

        //加载tom所需的依赖
        string[] ad_names = dic_AB[ab_name].depends_name;
        for (int i = 0; i < ad_names.Length; i++)
        {
            string dir_path_depends = Path.Combine(Application.persistentDataPath, ad_names[i]);

           //加载依赖时,直接加载出其ab包即可,不需要分解其依赖类型再去实例,unity自会处理
            AssetBundle.LoadFromFile(dir_path_depends);
           //所以下面部分就不需要了
           // StartCoroutine(LoadABFormStream(dir_path_depends));
        }

    }

相关方式实现

/// <summary>
    /// 从字节文件读取ab,并且实例化
    /// </summary>
    /// <param name="dir_path"></param>
    /// <returns></returns>
    IEnumerator LoadABFormStream(string dir_path)
    {
        FileStream fileStream = new FileStream(dir_path, FileMode.Open, FileAccess.Read);
        AssetBundleCreateRequest request = AssetBundle.LoadFromStreamAsync(fileStream);
        yield return request;

        AssetBundle myLoadedAssetBundle = request.assetBundle;
        if (myLoadedAssetBundle == null)
        {
            Debug.Log("Failed to load AssetBundle!");
            yield break;
        }
        //实例化ab
        InstanceAB_FormAssetBundle(myLoadedAssetBundle, myLoadedAssetBundle.name);
        fileStream.Close();
    }
     private void InstanceAB_FormAssetBundle(AssetBundle assetBundle, string obj_name)
    {

        Object gameObject = null;
        if (obj_name.Contains(".mat"))
        {
            gameObject = assetBundle.LoadAsset<Material>(obj_name);
            Instantiate<Material>((Material)gameObject);
        }
        else if (obj_name.Contains(".prefab"))
        {
            gameObject = assetBundle.LoadAsset<GameObject>(obj_name);
            Instantiate<GameObject>((GameObject)gameObject);
        }
    }
posted @ 2019-05-28 21:13  Jeanc  阅读(434)  评论(0编辑  收藏  举报