Bootstrap

Unity AssetBundle 打包笔记

若要更详细地学习AssetBundle内容,推荐看编辑器自带的官方文档"点击Help-UnityManual",Working in Unity - Advanced Development - AssetBundles标签下的大概9篇文章(若左边不显示目录,换一个浏览器就好了).

目录

一.功能

二.介绍

三.流程

四.实操

第一步:添加设置资源

第二步:编写运行打包脚本

第三步:加载提取实例化AssetBundle压缩包里的资源

五.打包分组方法

1.可参考的方法

2.具体要考虑的影响分组的因素

六.依赖打包与加载实操

七.加载AssetBundle包的4种方法

1.从内存中加载AssetBundle包(传入byte[]字节数组类型参数,需要using System.IO;命名空间)

2.从文件中加载AssetBundle包(传入string类型路径)

3.使用WWW.LoadFromCacheOrDownload从网络或本地加载AssetBundle包(已弃用)

4.使用UnityWebServer从从网络或本地加载AssetBundle包

八.从下载/加载好的AssetBundle包种加载资源

 九.通过AssetBundle.manifest文件加载其某个包的所有依赖包

十.从内存中卸载AssetBundle包

卸载的2种方式:

十一.文件校验

1.校验码

2.检验文件完整性原理

十二.其他

1.利用AssetBundle更新资源(打补丁)

2.常见问题

3.AssetBundle浏览工具插件(Unity Asset Bundle Browser Tool)



一.功能

AssetBundle是一个压缩资源的压缩包,然后在游戏运行的时候动态加载。

1.压缩是因为要减小包大小,方便网络传输。

2.资源包括:美术资源(模型 贴图) / 声音资源 (音效 音乐) / 工程资源(场景 预制体 材质 shader)等等。

二.介绍

1.AssetBundle会保存资源的互相的依赖关系。

2.AssetBundle可以使用两种个压缩方法:LZMA和LZ4。

3.AssetBundle压缩包中有两类文件:序列化文件和源文件。

         1)序列化文件(serialized file):资源被打碎放在一个对象中,最后统一被写进一个单独的文件(只有一个)。比如预制体就是这么处理。

         2)源文件(resource file):某些二进制资源(图片/声音等)被单独保存,方便快速加载。

三.流程

1.指定资源的AssetBundle属性。(xxxa/xxx)这里xxxa会生成目录,名字为xxx。

2.用代码构建AssetBundle包。

3.把AssetBundle上传到服务器。

4.在游戏里加载AB包和包里面的资源。

四.实操

第一步:添加设置资源

1.添加资源

可以从AssetStore中下载一个免费的素材:

Project窗口搜索"texture"(贴图) -> Search选择"Asset Store" -> 在"Free Asset"中选择一个素材 -> 查看Inspector窗口里显示的信息,选择一个"Size"小一些的 -> 点击"Import package".

2.设置需打包的资源的标签+后缀(其实就是对资源进行分组,分组不是划分文件夹,而是划分一个AssetBundle)

先把需要打包的资源做成预制体(先拖到场景中,再拖到Project文件中) -> 选中预制体 -> 把Inspector窗口底部的预览窗口向上拉开 -> 设置"AssetBundle"的标签(用/可以划分文件夹,比如scene/wall)+后缀(不建议用缩写).

注意:

1.用重复资源的多个物体,可以打在一个包中,比如两个预制体共用1个材质球.打成1个包的方法:标签和后缀设置相同.具体分组方法参考下面"五.打包分组方法".

2.新标签输入完需要"回车"确认.

3.标签和后缀名都是默认用小写字母的,大写字母会自动改成小写字母.

第二步:编写运行打包脚本

3.编写打包脚本

打包的脚本是Unity编辑器的插件,因为其不在运行时使用,显示在菜单列中.(可以放在自己建的专门放插件的Editor文件中).

BuildPipeline.BuildAssetBundles的第2个参数-打包选项:

1 BuildAssetBundleOptions.None(推荐):压缩算法为LZMA,压缩包体小,但加载时间长,因为使用其中任何一个资源都需要整体解压缩.解压后会用LZ4重新压缩.LZ4算法,压缩包稍大,但使用部分资源只需要部分解压.所以下载可以使用LZMA,下载后用LZ4保存到本地.

2 BuildAssetBundleOptions.UncompressedAssetBundle :不压缩,包大,加载快.

3 BuildAssetBundleOptions.ChunkBasedCompression:按照块(每个资源分为一个块)压缩,压缩率没有LZMA高,但是可以加载指定资源而不需要解压全部.所以可以得到与不压缩相媲美的加载速度,并且比不压缩文件要小.

其他打包模式查看:编辑器Help - UnityManual - Working in Unity - Advanced Development - AssetBundles - Building AssetBundles文章.

using UnityEditor;     //BuildPipeline需要该命名空间
using System.IO;       //Directory需要该命名空间,因为文件夹不会自动创建,这里手动创建
//打包必须且只需在编辑器下打包,不需要打包,只需要点击一下

public class CreatAssetBundles //因为只需要编辑器,所以不需要继承MonoBehaviour
{
    [MenuItem("Assets/Build AssetBundles #a")]//把该打包方法放在菜单栏中,方便点击使用,快捷键设置为shift+a(#代表shift)
    static void BuildAllAssetBundles()
    {
        string dir="AssetBundles";
        if(Directory.Exists(dir)==false)//手动检测路径,没有就创建文件夹
        {
            Directory.CreateDirectory(dir);
        }
        BuildPipeline.BuildAssetBundles(dir,BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
        //官方推荐,但是提示已弃用
        //BuildPipeline.BuildAssetBundles的3个参数:路径(不会自动创建),模式,平台(AssetBundle有平台限制)
    }
}

4.执行打包

点击菜单"Asset" -> "Build AssetBundles",根目录出现代码里手动创建的AssetBundles文件夹和内容就说明成功了.

5.我的报错

正常情况到上面第4步就成功了.

菜单键+文件夹都有,但是文件夹内没有内容~~Unity编辑器出现了3个报错:

1) The type or namespace name 'MenuItemAttribute' could not be found (are you missing a using directive or an assembly reference?)找不到MenuItemAttribute

2)The type or namespace name 'MenuItem' could not be found (are you missing a using directive or an assembly reference?)找不到MenuItem

3)Error building Player because scripts had compiler errors.编译器错误

解决办法:MenuItemMenuItemAttribute只需要using UnityEditor命名空间,报错是因为我智障创建了俩文件夹放了俩打包脚本,导致冲突,删掉一个就好了.

6.AssetBundles包体介绍

每个打包文件都配置一个.manifest清单文件:

AssetBundles.manifest:记录所有AssetBundle包,到时候会根据这里记录的路径加载资源.

其余每个包的.manifest:记录其依赖关系.

.manifest文件解读:

CRC:校验码,校验文件是否完整.(对应另外一种校验算法叫MD5)

Assets:列出该包中包含的资源,包括相对路径

Dependencies:列出该包的依赖关系,包括绝对路径

第三步:加载提取实例化AssetBundle压缩包里的资源

7.删除场景中已打包成AssetBundle压缩包的资源,用下面AssetBundle压缩包中的资源来代替.

8.写脚本加载资源:创建一个空物体,挂上下面的脚本,用来加载提取并实例化AssetBundle压缩包的资源.

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

public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        AssetBundle ab=AssetBundle.LoadFromFile("AssetBundles/scene/wall.unity3d");
        //AssetBundle.LoadFromFile同步加载AB包,返回一个AssetBundle类型的一个对象(最后的.unity后缀要写上)
        //这里的AssetBundle是内存里的一个类/对象,然后他的另一层含义是它加载的在硬盘上的"wall.unity3d"这个AssetBundle资源压缩包
        GameObject wallPrefeb=ab.LoadAsset<GameObject>("Cube");//取得加载的AssetBundle资源压缩包中的名为"Cube"的资源并返回为GameObject类型
        Instantiate(wallPrefeb);//实例化资源
        
        //这里是实例化所有的物体(一般都是预制体形式打包的),忘记资源的名字也可以用该方法查看
        /*Object[] objs=ab.LoadAllAssets();
        foreach(Object o in objs)
        {
           Instantiate(o); 
        }*/
    }
}

五.打包分组方法

1.可参考的方法

1)逻辑实体分组

    界面(每个/所有分成一个包): 内容包括贴图和布局信息.

    角色(每个/所有分成一个包): 内容包括模型和动画.

    所有场景共享的资源: 内容包括贴图和模型.

2)类型分组

    声音/shader/模型/材质分别分成一个包.

3)按照实际使用分组

    某一时间要一起使用的所有资源(比如角色(模型)/贴图/声音,像材质和shader还是建议按类型打包)分成一个包,比如每个关卡一个包,或者每个场景一个包.

2.具体要考虑的影响分组的因素

1)经常更新/不经常跟新    _减少包体大小

2)需要同时加载使用的     _减少包的数量

3)共享的资源(依赖打包)   _减少冗余

4)同时加载的小包合并      _减少包的数量(多次加载的启动总时长会比较耗时)

5)同一个资源的两个版本用后缀区分  _易找(后缀不同虽然会打包出俩文件,但似乎还是在同一个包里)

六.依赖打包与加载实操

目的:减少重复的资源,从而减小包体大小(共享的资源都打在一个包里,比每个包里都包括这个资源肯定要节省n-1倍的大小,而贴图是主要影响包体大小的因素).

1.依赖打包方法:共享的资源单独打一个包,把这些共享的资源的标签和后缀设置成同一个AssetBundle包名就可以了,然后打包时unity会自动把其他引用这些资源的包体加上依赖关系.

2.依赖加载方法:把共享包放在所有依赖该包的前面加载,后面引用有依赖的资源的时候unity会自动找到前面你已经加载的共享包里的资源.(有依赖的资源,只会用依赖的包里的资源)例如

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        AssetBundle abDepend=AssetBundle.LoadFromFile("AssetBundles/share.unity3d");//若要保证显示效果正确,所以尽量先加载被依赖的包
        
        AssetBundle ab=AssetBundle.LoadFromFile("AssetBundles/cube.unity3d");//依赖Share中的贴图和材质资源
        GameObject wallPrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(wallPrefeb); 
    }
}

其实被依赖的共享包也可以后面加载:比如按键之后再加载材质和贴图,也可以动态刷新,但是之前会有一段材质丢失的时期.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        AssetBundle ab=AssetBundle.LoadFromFile("AssetBundles/cube.unity3d");
        GameObject wallPrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(wallPrefeb);
    }
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            AssetBundle.LoadFromFile("AssetBundles/share.unity3d");//加载共享包,包括材质和贴图
        }
    }
}

更多依赖打包的相关内容查看:编辑器Help - UnityManual - Working in Unity - Advanced Development - AssetBundles - Asset Bundle Dependencies文章.

七.加载AssetBundle包的4种方法

1.从内存中加载AssetBundle包(传入byte[]字节数组类型参数,需要using System.IO;命名空间)

1)异步加载 AssetBundle.LoadFromMemoryAsync(),返回AssetBundleCreateRequest类型.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;    //File文件类在该命名空间中
public class LoadFromFileExample : MonoBehaviour
{
    IEnumerator Start()//yield需要所在函数是IEnumerator协程类型的
    {
        //共享包
        string pathshare="AssetBundles/share.unity3d";
        AssetBundleCreateRequest requestshare=AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(pathshare));
        yield return requestshare;
        //AssetBundle share=requestshare.assetBundle;//如果不修改依赖包中加载的内容,则可以不用这一步
        
        //资源包
        string path="AssetBundles/cube.unity3d";
        AssetBundleCreateRequest request=AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));//返回AssetBundleCreateRequest创建需求型数据
        yield return request;//等待加载完毕
        AssetBundle ab=request.assetBundle;//获取请求的来的assetbundle包
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

2)同步加载 AssetBundle.LoadFromMemory(),返回AssetBundle类型.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;    //File文件类在该命名空间中
public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        string pathshare="AssetBundles/share.unity3d";  //共享包
        string path="AssetBundles/cube.unity3d";        //资源包
        AssetBundle ab=AssetBundle.LoadFromMemory(File.ReadAllBytes(path));
        AssetBundle abshare=AssetBundle.LoadFromMemory(File.ReadAllBytes(pathshare));
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

2.从文件中加载AssetBundle包(传入string类型路径)

1)异步加载 AssetBundle.LoadFromMemoryAsync(),返回AssetBundleCreateRequest类型.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    void Start()
    {
        string pathshare="AssetBundles/share.unity3d";
        string path="AssetBundles/cube.unity3d";
        AssetBundleCreateRequest requestshare=AssetBundle.LoadFromFileAsync(pathshare);
        AssetBundleCreateRequest request=AssetBundle.LoadFromFileAsync(path);
        AssetBundle ab = request.assetBundle;
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

2)同步加载 AssetBundle.LoadFromMemory(),返回AssetBundle类型.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    void Start() 
    {
        string pathshare="AssetBundles/share.unity3d";
        string path="AssetBundles/cube.unity3d";
        AssetBundle abshare=AssetBundle.LoadFromFile(pathshare);
        AssetBundle ab =AssetBundle.LoadFromFile(path);
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }   
}

3.使用WWW.LoadFromCacheOrDownload从网络或本地加载AssetBundle包(已弃用)

WWW.LoadFromCacheOrDownload(@path,版本号);//已弃用,被下面第4种方法替代.若需全部更新可以修改版本号

1)从本地加载

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    IEnumerator Start() 
    {
        while(Caching.ready==false)//cache缓存是否准备好
        {
            yield return null;//未加载好则暂停一帧
        }

        string path="file://G:\\UnityProjects\\CubeMonsterismtryAB\\AssetBundles\\cube.unity3d";
        //这里路径用"/",或用"\\"(因为\是转义字符),必须加上file://或file:///前缀,还要使用绝对路径
        WWW www =WWW.LoadFromCacheOrDownload(@path,1);//如果报错路径前面加上@
        yield return www;//www加载好继续

        if(string.IsNullOrEmpty(www.error)==false)//有错误则输出错误并中断协程(www不会自动报错而是继续执行)
        {
            Debug.Log(www.error);
            yield break;
        }

        AssetBundle ab = www.assetBundle;
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

2)从服务器上加载

自己搭建本地服务器,注意:

1..使用服务器时需要手动打开NetBox2.exe服务器.

2..手机在同一局域网下(局域网IP)可以访问这个本地服务器,可以运行cmd->输入ipconfig回车->查看WLAN的Pv4的地址(局域网IP).

首先搭建服务器:

1.用NetBox2在本地搭建一个简单的网站服务器(NetBox2.exe所在文件夹,该文件夹路径名为localhost),方便测试.

 下载NetBox2.exe,然后在同目录创建index.html主页文件,可以用记事本打开修改添加文字内容.

2.把AssetBundles文件夹(包括所有的AssetBundle包)放到同NetBox2.exe的目录下.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
IEnumerator Start() 
    {
        while(Caching.ready==false)//cache是否准备好
        {
            yield return null;//未加载好则暂停一帧
        }

        string path="http://localhost//AssetBundles//cube.unity3d";
        WWW www =WWW.LoadFromCacheOrDownload(@path,1);
        //WWW.LoadFromCacheOrDownload(uri路径,版本号,CRC完整性校验码);还有多种衍生不同的参数
        //CRC:完整则CRC码与清单manifest中的CRC码一致,否则不一致则会从新从服务器下载
        yield return www;

        if(string.IsNullOrEmpty(www.error)==false)
        {
            Debug.Log(www.error);
            yield break;
        }

        AssetBundle ab = www.assetBundle;
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

4.使用UnityWebServer从从网络或本地加载AssetBundle包

1.创建本地/服务器下载需求(本地服务器需要手动打开NetBox2.exe,搭载本地服务器的方法查看上面"3.2)")

2.发送并等待下载完成

3.取得AssetBundle包(有2中)

4.提取包中资源

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;     //UnityWebRequest所需命名空间
public class LoadFromFileExample : MonoBehaviour
{
    IEnumerator Start() 
    {
        //string uri=@"file://G://UnityProjects//CubeMonsterismtryAB//AssetBundles//cube.unity3d";    //从本地文件下载包
        string uri="http://localhost//AssetBundles//cube.unity3d";                //从服务器下载包(包括本地服务器),加不加@都行
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uri); //创建获取包的请求
        yield return request.Send();                                              //发送获取包的请求,yield等待下载完成
        AssetBundle ab=DownloadHandlerAssetBundle.GetContent(request);            //取得下载内容
        //或用这一行取得下载内容AssetBundle ab=(request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;//handler处理器
        //把下载的包保存到本地File.WriteAllBytes(本地地址,request.downloadHandler.data);
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

八.从下载/加载好的AssetBundle包种加载资源

常用的几种从包种加载资源的方法:(ab为AssetBundle类型数据,若资源较大(比如场景)可以用3/4异步加载的方式)

1.GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");  (GameObject/AudioClip/Texture...等)

2.Object[] objs=ab.LoadAllAssets();  (因为所有的资源类型可能包括多种,所以用父类型Object)

3.异步加载单个资源(返回AsstBundleRequest类型,需要yield等待加载完毕)

AssetBundleRequest request=ab.LoadAssetAsync<GameObject>("Cube");
yield return request;
GameObject cubePrefeb =request.asset as GameObject;

4.异步加载所有资源(返回AsstBundleRequest类型,需要yield等待加载完毕)

AssetBundleRequest request=ab.LoadAllAssetsAsync();
yield return request;
Object[] cubePrefeb=request.allAssets;

资源类型:GameObject(prefeb,模型)/AudioClip/Texture...等,这些所有的类型都继承自Object类型.(那场景呢???)

加载AssetBundle方法参考文档,查看 : 编辑器Help - UnityManual - 选择Scripting API - 搜索AssetBundle - 选择第一个文档 - Static Methods

从AssetBundle加载资源方法参考文档,查看 : 编辑器Help - UnityManual - 选择Scripting API - 搜索AssetBundle - 选择第一个文档 - Public Methods

 九.通过AssetBundle.manifest文件加载其某个包的所有依赖包

1.加载名为AssetBundles的包,与其他AssetBunlde加载方法一致,例如用AssetBundle.LoadFromFile等方法.

2.从该包加载.manifest资源文件,与从包中加载GameObject等类型的资源方法一致,manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest"),括号种的名字不能更改.

3.获得所有依赖包的名字数组,manifest.GetAllDependencies("cube.unity3d"),返回一个字符串数组.

4.通过foreach遍历,加载所有依赖包.

附加:获取所有包的名字manifest.GetAllAssetBundles(),返回一个字符串数组.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
    void Start() 
    {
        AssetBundle manifestAB=AssetBundle.LoadFromFile("AssetBundles/AssetBundles");//获得依赖关系包
        AssetBundleManifest manifest=manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//获得依赖关系清单,文件名必须和类型一致不能修改

        //获得所有包的名字,manifest.GetAllAssetBundles()返回类型为string[]
        /* foreach(string name in manifest.GetAllAssetBundles())
        {  
            print(name);
        } */

        string[] strs=manifest.GetAllDependencies("cube.unity3d");//cube.unity3d包所有依赖的包的名字
        foreach(string name in strs)
        {
            print(name);
            AssetBundle.LoadFromFile("AssetBundles/"+name);
        }
        AssetBundle ab=AssetBundle.LoadFromFile("AssetBundles/cube.unity3d");
        GameObject cubePrefeb=ab.LoadAsset<GameObject>("Cube");
        Instantiate(cubePrefeb);
    }
}

十.从内存中卸载AssetBundle包

优点:减少内存占用.

缺点:有可能导致还在引用(包括场景的引用和代码的引用)的资源丢失.

附加:加载AssetBundle包,实质上是从硬盘上加载到内存中.

         可以在加载场景的时候,卸载上一个场景的AssetBundle包.

卸载的2种方式:

1.AssetBundle.Unload(true);(推荐) 卸载该包的所有资源

注意:该方法会使当前还被引用的资源丢失,所以需要确保该包的所有都已经不被引用了.

2.AssetBundle.Unload(false);卸载该包目前所有未被引用的资源

注意:再reload重新加载该包,那么之前未被卸载的该包资源也与reload的该包没有关联了,所以这些未被卸载的资源会导致内存滥用,所以不推荐该方法

未被卸载的资源卸载方法:1)Resources.UnloadUnusedAssets(需要先把这些资源的引用设置为null,怎么设置???).

                                         2)场景切换时会自动调用Resources.UnloadUnusedAssets,卸载未被使用的资源.

十一.文件校验

1.校验码

1)原理:通过算法,根据数据生成一个校验码,只要数据不同,那么校验码就不同.

2)各种校验码算法:CRC(AsseBundle使用):16位二进制/32位二进制,一般称作CRC值,安全性(检错能力)较弱,运行算法快,一般用来通信数据校验.

                              MD5:128位二进制(16字节),一般称作哈希值(Hash)或散列值,安全性很高,(算法是不可逆的)但被破解了,运行算法比较慢,一般用于安全领域,比如安全校验 数字签名,加密方法:把校验值存到数据库而不是存储数据;有时也被用来通信数据校验.

                              SHA1:160位二进制(20字节),一般称作哈希值(Hash)或散列值,安全性最高,运行算法比较慢,一般用于安全领域,比如安全校验 数字签名,加密方法:把校验值存到数据库而不是存储数据.

2.检验文件完整性原理

1)传输文件时,把完整文件的校验码与文件一起传输;

2)传输完成后,根据同种算法和传输完毕的数据再次计算出一个校验值;

3)比对校验码与算出来的校验值是否一致,若一致则文件完整,否则文件不完整.

十二.其他

1.利用AssetBundle更新资源(打补丁)

步骤:

1)记录本地已经下载的AssetBundle的列表及其版本号

2)记录服务器上的AssetBundle的列表及其版本号

3)比对信息,下载需要更新的资源

具体可查看:编辑器Help - UnityManual - Working in Unity - Advanced Development - AssetBundles - Patching with AssetBundles文章.有关于热更新的方法,推荐查看文档.

2.常见问题

具体可查看:编辑器Help - UnityManual - Working in Unity - Advanced Development - AssetBundles - Troubleshooting文章.

1)依赖包重复问题

解决方法:1)把共享某些资源的所有资源和共享资源打包到一起(不同时更新的,或者不同时使用的话,会导致包体过大)

               2)分割不在同一时间使用的资源

               3)把共享的部分打成单独包(推荐)

2)图集重复问题

unity会自动把未设置Packing Tag(图集标签)的2D图片(Sprit2(2D and UI)类型)打包成1个图集,AssetBundle打包时若是要打包某一个在图集中的1张图片,整张图集都打包进去,导致包体过大,且图集重复.

解决方法:1..把图集打包到1个单独的AssetBundle包中.

                2..设置图片的Packing Tag指定打包到指定的名字的图集中,即分成多个图集(选择图片-Inspector窗口- Packing Tag).

3)Android贴图问题

   ETC1不支持透明通道,推荐使用ETC2,有关于移动设备的贴图优化方法,推荐查看文档.

4)iOS文件处理重复fixed in Unity5.3.2p2

3.AssetBundle浏览工具插件(Unity Asset Bundle Browser Tool)

具体可查看:编辑器Help - UnityManual - Working in Unity - Advanced Development - AssetBundles - Unity Asset Bundle Browser tool文章.该插件不是官方的,是一个GitHub上的开源的非常好用的插件,轻量级,方便继承,不会对现有代码有什么影响.(GitHub上Unity官方网址:Unity Technologies,有很多工具插件.)

1)下载安装适用:

1.下载:点击上面文章中的GitHub链接 - releases(发布版本,不一定是最新的) - 第一个版本的Source code(zip)压缩包

2.安装:把文件夹直接拖到Assets文件夹中,注意Editor的路径和名称不能改变.

3.使用:unity编辑器Windows - AssetBundle Browser.

2)功能:

1.在编辑器内查看所有包的清单信息(打包前设置标签后就可以查看,新设置好标签后刷新),包括包列表/内容列表/大小/依赖等等信息.

2.打包设置:比如平台(BuildTarget)/输出路径(Output Path)/清除目标路径文件夹/复制到不压缩文件夹中(Copy to StreamingAssets中/压缩方法(LZMA/LZ4),比如开始界面等一打开游戏需要马上能运行的内容推荐不压缩,后期更新的关卡则可以压缩)

 

 

 

 

 

 

 

 

 

 

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;