浅谈热更新

热更新的好处

  • 迅速修复Bug,避免重新下载安装包,游戏内部更新修复Bug
  • 提升玩家的留存率,避免玩家因为超大的安装包而流失
  • 迅速换”内核”

AB包

AB包定义

  • 特定于平台的资产压缩包,优点类似于压缩文件

  • 资产包括:模型,贴图,预制体,音效,材质球等

Resources和AB包的区别

  • Resources打包时定死,作为只读,是无法进行修改的

  • 存储位置和压缩方式是可以自定义的,在后期可以动态进行更新

AB包的作用

  • 减少包体的大小【1.压缩资源,减少初始化包大小】
  • 热更新

AB包打包工具

  • AssetBundle Browser 教程🚩Unity自带的一款AB包打包工具
  • 自己制作,这个在文章中有所介绍

AssetBundle Browser的使用

1.首先需要的Packages Manager中下载

Packages Manager

AssetBundle Browser工具截图

2.制成预制体,并设定AssetBundle

如图所示,点击New,然后输入自定义名称,这里需要注意的便是名称只支持小写哦😁

3.在AssetBundle Browser工具中Configure看到刚才命名好的素材了

4.下面我们熟悉一下AssetBundle Browser工具中的Bulid选项中各部分的作用

【1】基础设置

  • Bulid Target:主要是打包发布的平台【这里其实平台还是很多的,包括Windows,iOS】
  • Output Path: 输出路径[这个主要是打包好的文件存放到哪个位置]
  • Clear Floders 构建之前清空文件夹(会把文件夹删除)
  • Copy to StreamingAssets:拷贝至StreamingAssets文件夹【这个建议勾选

【2】高级设置

  • Compression:选择压缩格式【AssetBundle Browser工具内置了三种压缩方式】

    ①. No Compression(这个主要是不进行压缩,也就是说将素材大小原封不动的打包出来,最大的好处便是打包出来会相比较其他两种快一些,但是缺点也显而易见,便是包体会相比较其他两种大小会比较大,还是建议用于一些资源大小比较小的时候)

    ②. Standard Compression[LZMA](标准压缩方式,这种最大的好处便是能将包体压缩到最小,但是缺点便是1.由于压缩到最小,所以解压出来也同样会更慢,2.这种压缩方式在使用某个资源时,解压过程中会将所有资源全部解压,这样会导致资源的浪费和性能的消耗)

    ③. Chunk Based Compression[LZ4](基于块的压缩方式,这种压缩相比较LZMA标准压缩方式压缩率较少一些,但是最大的好处便是随使随用,即需要什么解压什么,减少了资源的浪费和性能消耗)

  • Exclude Type Infomation 这个的勾选与否,主要是看资源包中是否需要排除类型信息

  • Fource Rebuild 重新打包时是否需要重新构建包,主要用于在包中文件有变化时重新对所有包中资源进行资源的构建,但是不会清除已经删除的包,其实这个相比较建议使用 Clear Floders即可

  • Ignore Type Tree Changes 增量构建检查时,忽略类型的更改【用途不大

  • Append Hash 将文件哈希值附加到资源包名中【实际使用用途不大

  • Strict Mode 如果勾选此项,在打包过程中若发现错误,会终止打包【为了包的正常性,建议勾选此项

  • Dry Run Bulid 运行时打包

基本加载AB包(Windows ,移动端)

普通AB包加载

①. 首先需要定义AB包,也就是说加载AB包

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

②. 加载AB包中资源 需要用ab.LoadAsset(),如果单纯用名字加载,会出现同名不同类型素材冲突的问题,所以在这里建议用泛型加载或者Type指定类型 这里需要注意的一点便是lua是不支持泛型的哦,建议多使用Type指定类型

1
2
GameObject objOne = ab.LoadAsset<GameObject>("Cube");//用泛型加载立方体
GameObject objTwo = ab.LoadAsset("Cube",typeof(GameObject)) as GameObject;//用Type指定类型加载立方体

③. 实例化物体,这里就比较简单了Instantiate即可,如果想指定位置和角度也是可以的

1
Instantiate(objTwo);

④. 当加载另一个资源,况且与上一个物体属于同一个AB包,不可以重新加载AB包,否则会出现错误问题,只需直接加载AB包资源即可

1
2
GameObject objThree = ab.LoadAsset<GameObject>("Sphere");//用泛型加载圆体
GameObject objFour = ab.LoadAsset("Sphere",typeof(GameObject)) as GameObject;//用Type指定类型加载立方体

这样简单的AB包加载已经OK了

异步AB包加载

①. 由于是异步加载,所有这里需要引入一个新的类AssetBundleCreateRequest,这个类主要是用于AssetBundle用来异步创建请求的,所以加载AB包就可以这样写【这里为了方便整合成一个协程方法,通过StartContinue调用即可】

1
2
3
4
5
6
7
8
9
10
11
12
13
IEnumerator LoadAB_Res(string AB_Name,string Res_Name)
{
//第一步:加载AB包
AssetBundleCreateRequest abcr =
AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + AB_Name);
yield return abcr;
//第二步:加载资源
AssetBundleRequest abq=abcr.assetBundle.LoadAssetAsync(Res_Name,typeof(Sprite));
yield return abq;
//由于是实现效果,所以没有用泛型,在后面会补上,这里拟定加载的是图片
//testImg是Image类型的,记得继承using UnityEngine.UI;哦
testImg.sprite=abq.asset as Sprite;
}

【4】移除/卸载AB包

在之前的代码已经完成了最基本的AB包加载和AB包异步加载,在AB包不用时需要移除AB包,即

1
2
3
4
5
//这里需要填写bool值,若为false,即卸载所有加载的AB包,不会把通过AB包加载的资源也卸载,否则反之
AssetBundle.UnloadAllAssetBundles(bool 类型);
//若删除某个AB包时,则可以直接要填写bool值,若为false,即卸载加载的AB包,不会把通过AB包加载的资源也卸载,否则反之
AssetBundle ab=AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/"+"model");
ab.Unload(bool 类型);

这个AB包加载的基本操作就OK咯,复一份源码作为参考💯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 public Image testImg;
void Start()
{
//第一步:加载AB包
AssetBundle ab=AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/"+"model");
//第二步:加载AB包中的资源
//只是用名字加载,会出现同名不同类型资源分不清
//建议大家用泛型加载或者Type指定类型
//GameObject objOne = ab.LoadAsset<GameObject>("Cube");
GameObject objTwo = ab.LoadAsset("Cube",typeof(GameObject)) as GameObject;
Instantiate(objTwo);
//卸载所有加载的AB包,参数为true时,会把通过AB包加载的资源也卸载
AssetBundle.UnloadAllAssetBundles(true);
StartCoroutine(LoadAB_Res("head", "19167f78aaa0dfbde65f96d152d097a200573C"));
}

IEnumerator LoadAB_Res(string AB_Name,string Res_Name)
{
//第一步:加载AB包
AssetBundleCreateRequest abcr =
AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + AB_Name);
yield return abcr;
//第二步:加载资源
AssetBundleRequest abq=abcr.assetBundle.LoadAssetAsync(Res_Name,typeof(Sprite));
yield return abq;
testImg.sprite=abq.asset as Sprite;
}
此文章部分来源于唐老狮的Unity中Lua热更新解决方案,有条件可以支持一下