Unity用户手册-AssetBundle

AssetBundle

什么是AssetBundle?

AssetBundle实际上是一个资源管理包。AssetBundle 包含了两个部分:数据头以及数据段。数据头内包含了 AssetBundle 的元数据信息,比如它的标识符、压缩类型、manifest 等等。这里的 manifest 是一个以 Object 名称作为键的查找表,用以指定 AssetBundle 中给定 Object 的位置。数据段内包含了序列化 Asset 生成的原始数据,内容会依据压缩算法变化。

AssetBundle 具有如下优点:

  • 可以按需加载和释放 Asset 。
  • 自带压缩算法,可以按需定制,减少包体容量。
  • 自带版本更新内容,可以进行增量更新。
  • 内部包含了对 Object 的引用关系。

 

第一种是在磁盘上的实际文件,就像一个容器,一个文件夹,可以包含其他文件(模型,纹理,预制,音频,甚至整个场景)。没有后缀名称的AssetBundle文件,这个文件是包含了所有的依赖关系的配置文件,加载AssetBundle就是加载的这个文件,有后缀名称的manifest文件,只是用来做本地依赖关系和增量打包的时候用的。

第二种是运行时加载的AssetBundle对象,包含添加到AssetBundle中的所有资产的路径映射,及资产的对象。

 

UnityWebRequestAssetBundle获取AssetBundle

public void LoadResource(string resName, string filePath)
    {
        StartCoroutine(LoadResourceCorotine(resName, filePath));
    }

    IEnumerator LoadResourceCorotine(string resName, string filePath)
    {
        AssetBundle ab = null;
         UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(@"http://localhost/AssetBundles/" + filePath);
         yield return request.SendWebRequest();
         if (request.isNetworkError || request.isHttpError)
        {
            Debug.Log(request.error);
        }
        else
        {
            ab = DownloadHandlerAssetBundle.GetContent(request);
            //ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
        }
        if (ab == null)
        {
            yield break;
        }
        //同步加载
        //GameObject gameObject = ab.LoadAsset<GameObject>(resName);
        //异步加载
        AssetBundleRequest abRequest = ab.LoadAssetAsync<GameObject>("Cube");
        yield return abRequest;
        GameObject ob = abRequest.asset as GameObject;
        Instantiate(ob);
        // 卸载所有的资源
        ab.Unload(true);
    }

 

UnityWebRequest获取文本文件,并写入到固定目录

IEnumerator LoadResourceCorotine()
    {
        UnityWebRequest request = UnityWebRequest.Get(@"http://localhost/fish.lua.txt");
        yield return request.SendWebRequest();
        string str = request.downloadHandler.text;
        File.WriteAllText(@"D:\BaiduNetdiskDownload\xLua_unity\XluaProjects\XluaProjects\PlayerGamePackage\fish.lua.txt", str);
        UnityWebRequest request1 = UnityWebRequest.Get(@"http://localhost/fishDispose.lua.txt");
        yield return request1.SendWebRequest();
        string str1 = request1.downloadHandler.text;
        File.WriteAllText(@"D:\BaiduNetdiskDownload\xLua_unity\XluaProjects\XluaProjects\PlayerGamePackage\fishDispose.lua.txt", str1);
    }

 

一、AssetBundle的加载

 

AssetBundle.LoadFromFile 从磁盘上的文件同步加载AssetBundle

AssetBundle.LoadFromFileAsync 从磁盘上的文件异步加载AssetBundle

函数支持任何压缩类型的包。在lzma压缩的情况下,数据将被解压缩到内存中。可以直接从磁盘读取未压缩和块压缩(chunkcompressed,也就是LZ4)的包。

 

AssetBundle.LoadFromMemory 从内存同步创建AssetBundle

AssetBundle.LoadFromMemoryAsync 从内存异步创建AssetBundle

使用此方法从字节数组创建AssetBundle。当您使用加密下载数据并需要从未加密的字节创建AssetBundle时,这非常有用。

 

AssetBundle.LoadFromStream 从托管流同步加载AssetBundle

AssetBundle.LoadFromStreamAsync 从托管流异步加载AssetBundle

函数支持任何压缩类型的包。在lzma压缩的情况下,数据将被解压缩到内存中。可以直接从磁盘读取未压缩和块压缩(chunkcompressed,也就是LZ4)的包。

在加载AssetBundle或捆绑包中的任何资产时,请勿释放Stream对象。它的寿命应该比AssetBundle长。这意味着在调用AssetBundle.Unload之后处理Stream对象。

 

LZ4算法是“基于块”的,因此当对象从一个LZ4压缩包加载时,仅用于该对象的相应块会被解压。

即使AssetBundle的其他块未解压缩,解压缩单个块允许使用包含的资产。

 

UnityWebRequestAssetBundle.GetAssetBundle 创建UnityWebRequest,优化用于通过HTTP GET下载Unity资产包

 

二、Asset的加载

AssetBundle.LoadAsset 从资源包中加载指定的资源

AssetBundle.LoadAssetAsync 从资源包中异步加载资源

 

AssetBundle.LoadAllAsset 加载当前资源包中所有的资源

AssetBundle.LoadAllAssetAsync 异步加载当前资源包中所有的资源

 

三、Asset的卸载

AssetBundle.Unload

卸载捆绑包中的所有资产,卸载释放与包内对象关联的所有内存。

AssetBundle.Unload(false) 仅仅销毁AssetBundle对象包含的资源,任何从此包中加载的实际对象保持不变。当然,也将无法从此AssetBundle包中加载任何其他对象。

AssetBundle.Unload(true) 销毁AssetBundle对象包含的资源,同时销毁从此包中加载的资源对象,即会释放AssetBundle.LoadAsset等加载的资源对象。如果场景中有游戏对象引用这些资源,则对它们的引用都会丢失。

 

Resources.UnloadAssets 释放指定的Asset

Resources.UnloadUnusedAssets 释放没有引用的Asset

 

AssetBundle的粒度

即每个AssetBundle包含多少资源

 

 

打包策略

 

  • 将公共依赖的资源打包到一个公共AssetBundle中,独立的资源打包到一个AssetBundle中
  • 将相同类型的资源(Shader、Atlas、Prefab、Material、Scene、动画、声音、特效等)打包成一个AssetBundle
  • 地图、Monster、Npc、角色、坐骑、神翼等根据配置进行打包
  • 根据资源间的引用关系,去除重复的资源

 

去除重复的资源

对于没有被指定打包的外部资源,如果多个ab包依赖了它,打包时该资源就会被多次打包进依赖它的ab包中,造成冗余。

解决方案:

建立了三个对应关系的字典:

Dictionary<string, Bundle> m_BundleDic = new Dictionary<string, Bundle>();

Dictionary<string, Asset> m_AssetDic = new Dictionary<string, Asset>();

Dictionary<string, string> m_AssetMapBundleDic = new Dictionary<string, string>();

m_BundleDic:维护了BundleName-Bundle对象对应关系的字典,其中Bundle对象中,维护了当前Bundle中所有的资源列表AssetList。

m_AssetDic:维护了AssetName-Asset对象对应关系的字典

m_AssetMapBundleDic:维护了AssetName-BundleName对应关系的字典

 

具体操作步骤:

1. 创建一个HashSet,确保所有的资源Asset在Bundle中是唯一的,不产生冗余。

1. 遍历m_BundleDic中每一个Bundle对象的AssetList;

2. 如果不在HashSet中,把Asset加入到HashSet中,否则,执行删除冗余操作;

3. 如果HashSet已经存在相同的Asset时,通过m_AssetMapBundleDic字典获得当前Asset对应的BundleName;

4. 如果当前Asset对应的BundleName在m_BundleDic中,表示多个ab包依赖了这个Asset,从对应的Bundle的AssetList中移除这个Asset。

5.如果当前Asset对应的BundleName不在m_BundleDic中,表示虽然多个ab包依赖了这个Asset,但是其中有一些并不需要打到ab包中,这时,需要把对应的Bundle从m_AssetMapBundleDic中移除。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值