AssetBundle 的简单认识

首先 AssetBundle是什么: 是把一些资源文件或场景文件以某种紧密的方式保存在一起的文件, 包含模型文件、纹理材质、场景 等

                                               AssetBundle中不能包含c#的脚本文件,一般获取它包含的文件,用作热更新

 加载AssetBundle包的方法

       一、加载的AB包的路径

              1、加载AB包, 参数: 加载的AB包的路径

            AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + " ");

             2、从AB包中加载所需要的资源   (泛型指定:需要加载的资源类型  , 参数: 资源的名字)

            GameObject bgPrefab = ab.LoadAsset<GameObject>("Bg");

            3、实例化

       二、使用www加载本地资源

             1、注意 需要在路径前加:     file://

                       WWW www = new WWW("file://" + Application.streamingAssetsPath + "/AssetBundle11111/prefab");

              2、从www中获取加载到的AB包
                      AssetBundle ab = www.assetBundle;

             3、加载AB包中的资源

             4、实例化

          注意事项: AB包不能重复的加载,在卸载前只能加载一次                             

             可能问题:1、检查路径是否正确 。 2、检查你加载的资源的名字是否正确。

                                 因为依赖的特性 :注意:要同时把AB包依赖的AB包也加载进来,否则可能会出现资源的丢失。            

          获取AB包的依赖

                          加载单一的特殊的AB包。

                         从特殊的AB包中去获取AssetBundleManifest类型的文件

                         通过AssetBundleManifest文件去获取指定名字的AB包的所有的依赖 

                        string[] all_arr = singleManifest.GetAllAssetBundles();  //  获取所有AB   包的名字,返回一个字符串数组

                       string[] dep_arr = singleManifest.GetAllDependencies("  ");   // 通过参数输入的名字,获取所有的依赖包

            AB包的卸载

                       Ab.Unload() 参数是true或false

                                         True:卸载AB包的同时把从AB包中加载的资源也同时卸载掉。

                                         False:只卸载AB包,不卸载从AB包中加载的资源。

打包AssetBundle    

     首先需要引用UnityEditor命名空间

      1. 先把资源在Editor下修改AssetBundle的名字

                           ( 修改的位置 就在 打开要打包的物体的 Inspentor面板的最下方  手动设置名字)

      2.利用下面代码BuildPipeline创建AssetBundle(选择一个文件路径,可以使用特性在[MenuItem("/")] 在上方创建一个选项)

     BuildPipeline. BuildAssetBundles(outPutPath,BuildAssetBundleOptions . ForceRebuildAssetBundle,BuildTarget.                                                                                             StandaloneWindow64); 

     参数:  1、 AB包的输出路径,  2、 打包的相关选项  , 3、 AB包使用的平台    

                    2 打包选项:BuildAssetBundleOptions

                                           CollectDependencies:包含所有的依赖项(默认开启)

                                            DeterministicAssetBundle:构建一个资源包(默认开启)

                                            UncompressedAssetBundle:在构建AB包时不压缩数据

                                            ChunkBasedCompression:在构建AB包时压缩数据(LZ4)

                                             ForceRebuildAssetBundle:强制性的重新进行打包

                                             AppendHashToAssetBundleName:把哈希码附加到名字的后面

    打包注意事项:

          1、检查路径是否在工程中存在或是否路径出错

          2、检查打包平台是否有问题

           3、AB包的名字里不能含有与打包输出文件夹的名字一致的(不区分大小写)

           4、有使用了UnityEditor命名空间脚本未放在Editor文件夹下。

    Unity 支持 AssetBundle的压缩模式

                  LZMA 、 LZ4 、 不压缩

   AssetBundle构建后的组成

                          AB包文件 + 该AB包所对应的Manifest文件

                                          Manifest文件        CRC: 循环冗余码       Assets:包含的资源的路径    Dependencies:依赖的AB包的路径

            注意: Manifest文件记录了所有的AB包的名字和其AB包的依赖信息

                                             

 

 

    方便的单例 获取AB包 脚本 : 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



/*
 *  1. 防止AB包的重复加载
 *  2. 对加载进来的AB包进行管理
 *  3. 对外提供一个加载AB包的方法
 *  4. 对外提供与一个卸载AB包的方法
 *  5. 对外提供一个获取加载完成的AB包的方法
 *  6. 对外提供一个从任意的AB包中加载资源的方法
 *  
 * */


public class AssetBundleManager
{

    #region 提供一个单例

    //1. 先定义一个静态私有的AssetBundleManager的一个对象
    private static AssetBundleManager instance;

    //2. 私有构造函数, 防止外部对齐进行实例
    private AssetBundleManager()
    {
        LoadSingleManifest();//把加载单一的Mnifest文件写构造力,只调用一次
    }

    //3. 创建一个静态方法或者是只读的静态属性对instance进行保护,以供外部调用一个非空的对象
    public static AssetBundleManager _Instance
    {
        get {
            if (instance == null)
            {
                instance = new AssetBundleManager();
            }
            return instance;
        }
    }

    #endregion


    #region 变量

    /// <summary>
    /// 存储了所有AB包的依赖的Manifest文件
    /// </summary>
    private AssetBundleManifest singleManifest = null;

    /// <summary>
    /// 提供一个字典去存储加载进来的AB包。键是AB包的名字,值是AB包
    /// </summary>
    private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

    /// <summary>
    /// 所有AB包的存储路径
    /// </summary>
    private string abPath = Application.streamingAssetsPath + "/AssetBundle/";

    /// <summary>
    /// 单一的AB包的路径
    /// </summary>
    private string singleABPath = Application.streamingAssetsPath + "/AssetBundle/AssetBundle";

    #endregion


    #region 方法

    /// <summary>
    /// 加载单一的Manifest文件
    /// 把加载单一的Mnifest文件写构造力,只调用一次
    /// </summary>
    private void LoadSingleManifest()
    {
        if (singleManifest == null)
        {
            //单一的Manifest文件需要从单一的AB包中去加载
            AssetBundle single = AssetBundle.LoadFromFile(singleABPath);
            //从ab包中加载manifest文件
            singleManifest = single.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            //单一的ab包只需要加载manifest文件,完成之后就卸载掉
            single.Unload(false);
        }

        if (singleManifest == null)
        {
            Debug.LogError("加载Mnifest文件失败,请检查路径是否正确!");
        }
    }


    /// <summary>
    /// 加载指定的AB包的所有依赖项
    /// </summary>
    /// <param name="abName">ab包的名字</param>
    private void LoadDependencies(string abName)
    {
        //加载所有依赖,先获取所有的依赖项
        if (singleManifest != null)
        {
            //先获取所有的依赖
            string[] deps = singleManifest.GetAllDependencies(abName);
            //循环加载依赖项
            for (int i = 0; i < deps.Length; i++)
            {
                //因为我们本身提供一个加载AB包的方法,那么可以直接调用该方法来加载有依赖项
                LoadAssetBundle(deps[i]);
            }
        }
        else
        {
            Debug.LogError("单一的Mnifest文件为null,请先加载");
        }
    }

    /// <summary>
    /// 加载AB包的方法
    /// </summary>
    /// <param name="abName">ab包的名字, 所有的AB包都是统一的路径</param>
    public void LoadAssetBundle(string abName)
    {
        //加载AB包, 先判断该名字的AB包是否加载了
        //因为我们是通过字典对加载进来的AB包做管理的,所有只需要判断字典中是否有该ab包名字的键来判断是否加载过该AB包
        if (!abDic.ContainsKey(abName))
        {
            //判断字典中未加载该AB包,所有需要加载AB包

            //加载AB包之前,先把依赖加载进来
            LoadDependencies(abName);//自己的方法

            AssetBundle ab = AssetBundle.LoadFromFile(abPath + abName);
            //需要把加载进来的ab包,添加到字典中
            abDic.Add(abName, ab);
        }
    }

    /// <summary>
    /// 卸载指定的AB包
    /// </summary>
    /// <param name="abName">ab包的名字</param>
    /// <param name="isUnloadAllLoadedObjects">是否把从AB包中加载到的资源全部卸载</param>
    public void UnloadAssetBundle(string abName, bool isUnloadAllLoadedObjects)
    {
        //卸载指定的AB包
        //先判断是否加载过
        if (abDic.ContainsKey(abName))//键存在证明加载过
        {
            //从字典访问AB包,并且卸载它
            abDic[abName].Unload(isUnloadAllLoadedObjects);
            //卸载完成之后,需要把该键值对从字典中移除
            abDic.Remove(abName);
        }
    }

    /// <summary>
    /// 卸载所有的AB包
    /// </summary>
    public void UnloadAllAssetBundle()
    {
        //卸载所有AB包,就是遍历字典,把字典里所有的AB包卸载
        //实际的AB包在字典中是值的存在,所有只需要遍历字典的值
        foreach (AssetBundle ab in abDic.Values)
        {
            ab.Unload(true);//卸载AB包
        }

        //清空字典
        abDic.Clear();
    }

    /// <summary>
    /// 获取指定的AB包
    /// </summary>
    /// <param name="abName">ab包的名字</param>
    /// <returns></returns>
    public AssetBundle GetAssetBundle(string abName)
    {
        //获取AB 包之前需要判断是否加载过AB包
        if (!abDic.ContainsKey(abName))
        {
            //未加载过AB包
            LoadAssetBundle(abName);//自己本身的加载AB包的方法
        }
        return abDic[abName];//从字典中获取AB包
    }


    /// <summary>
    /// 从指定的AB包中加载指定的资源资源
    /// </summary>
    /// <typeparam name="T">需要加载的资源的类型</typeparam>
    /// <param name="abName">ab包的名字</param>
    /// <param name="assetName">需要加载的资源的名字</param>
    /// <returns></returns>
    public T LoadAsset<T>(string abName, string assetName) where T : Object
    {
        //从指定的AB包中加载指定的资源,
        //先获取指定的AB包
        AssetBundle ab = GetAssetBundle(abName);//自己提供的获取AB包的方法
        //从ab包中获取资源  T是调用的外部指定的类型
        T asset = ab.LoadAsset<T>(assetName);

        return asset;
    }

    /// <summary>
    /// 从指定的AB包中加载指定的资源
    /// </summary>
    /// <param name="abName">ab包的名字</param>
    /// <param name="assetName">资源的名字</param>
    /// <returns></returns>
    public Object LoadAsset(string abName, string assetName)
    {
        //先获取指定的AB包
        AssetBundle ab = GetAssetBundle(abName);//自己提供的获取AB包的方法
        //从ab包中获取资源
        Object obj = ab.LoadAsset(assetName);
        return obj;
    }

    #endregion


}

                                           

                              

猜你喜欢

转载自blog.csdn.net/j_sbytc3/article/details/81460918