游戏热更教学系列(一)——AssetBundle学习
前言
目前的大部分的游戏现在都需要进行版本的更新,但是如果是每次更新都要重新下载完整的资源包,但是实际却只是更新了很小的一部分的话,那可能就会浪费玩家很多的流量去下载,如果本身软件的安装包就很大的话,可能就会浪费玩家很多的时间,这极可能会降低玩家的兴趣,所以就有了热更技术,每次更新的时候只需要更新一部分资源和代码就可以实现版本更新,这样就可以大大降低玩家下载的内容。
学习热更技术需要掌握的知识
想要学会热更技术,是需要掌握一些必要的知识的,热更主要就是更新游戏的资源和代码,用AssetBundle进行资源的热更,用Lua语言进行代码的热更,还需要会使用Lua的一些框架插件如XLua,toLua等。
一、AssetBundle的制作、打包与上传
AssetBundle,简称AB包,即资源包。主要就是用于资源热更,更新游戏中的资源。
1.AssetBundle的制作与打包
1.1 AB包的设置
随意选择一个资源,打开资源的Inspector面板,选择最下面的AssetBundle属性,如下:
如图中圆圈所示,有两个可选的框,第一个是打包后的资源包的名字,第二个你想要设置的资源包的后缀,这些都可以自己设置,注意事项:
- 设置的相同资源名,后缀必须相同,不然打包会报错
- 资源包的名字可以这样设置,比如“A/B”,这样设置,默认最后一个"/“所在的后面为资源包的名字,前面以”/"分隔,其他的均为打包资源包的根目录下的文件夹,会默认创建
- 资源包所依赖的其他的资源包如果也设置了,那依赖的资源包将不会打包到该资源包中
1.2 创建生成AB包的代码
Unity没有设置生成AB包的菜单,需要自己用代码写一个生成AB包的代码,可能是考虑到AB包只能在一个平台适用,而平台很多,不好统一吧。步骤如下:
- 在Assets文件夹下创建一个Editor文件夹
- 在Editor文件夹下创建一个C#脚本,并命名为CreateAssetBundle(这里可以自己任意命名)
- 代码如下:
using System.IO;
using UnityEditor;
//*************
//Author:HCL
//Time:2023-3-9
//
//**********
public class CreateAssetBundle
{
[MenuItem("Assets/Build AssetBundles")]//此为菜单显示的按钮,可以在菜单栏的Assets下看到Build AssetBundles,点击后就可以生成相应的AB包了
static void BuildAssetBundles()
{
string dir = "AssetBundles";//此为你想生成的AB包的文件夹根路径
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
//这个就是生成AB包的方法,参数说明:
//第一个参数:生成的AB包的文件夹根路径
//第二个参数:AB包压缩的方式,BuildAssetBundleOptions.None为默认的压缩格式
//第三个参数:AB包使用的目标平台,只能适用一个平台
BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}
}
完成以上步骤就可以生成AB包了,点击菜单栏的Assets的Build AssetBundles,等待打包完成,然后去到相应的文件夹中,比如上述代码中的AssetBundles,就可以看到打包好的所有资源包了,我这里任意举一个例子,来说明一下打包后所拥有的内容:
第一个就是对应的设置AB包时的文件夹路径的根路径,第二个是AssetBundles对应的所有AB包信息,第三个是AssetBundles对应的内部所有文件对应的AB包配置信息,每个打包后的根目录下都会生成这两个文件,比如打包的目录为AssetBundles,则会有AssetBundles,AssetBundles.manifest这两个文件,其他的就是对应的资源包和其对应的配置文件了,比如上图中的scenes.unity3d,这个就是打包的scenes资源包,后缀为unity3d,下面那个同名的scenes.unity3d.manifest就是其配置文件。下面主要来介绍一下两种manifest的一些内容:
- AssetBundles.manifest(打包文件夹的配置文件)
内容如下:
ManifestFileVersion: 0
CRC: 717295521
AssetBundleManifest:
AssetBundleInfos:
Info_0:
Name: share.unity3d
Dependencies: {}
Info_1:
Name: scenes.unity3d
Dependencies:
Dependency_0: scene/wall.unity3d
Info_2:
Name: scene/wall.unity3d
Dependencies:
Dependency_0: share.unity3d
字段信息 | 字段含义 |
---|---|
ManifestFileVersion | 所属的版本号 |
CRC | 所用的校验码,可用于校验数据是否正确,在下载时可以使用 |
AssetBundleInfos | 里面就是所有包含的内容信息了,各个信息以’Info_编号’分隔,如Info_0,Info_1,Info_2等,每个Info中,Name表示对应的资源包的相对路径,如share.unity3d指的是share.unity3d资源包, scene/wall.unity3d则指scene文件夹下的wall.unity3d资源包,Dependencies指的是每个资源包所对应的依赖包,多个依赖包以 ‘Dependency_编号’分割。 |
- scenes.unity3d.manifest(scenes.unity3d资源包的配置文件(这儿随便取了其中一个资源包))
内容如下:
ManifestFileVersion: 0
CRC: 1422320002
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 82c3676a6e3a884fe1fdc072123a3fae
TypeTreeHash:
serializedVersion: 2
Hash: 967e73a2549e95eedb6ef1a0d1b029f6
HashAppended: 0
ClassTypes:
- Class: 1
Script: {instanceID: 0}
- Class: 4
Script: {instanceID: 0}
- Class: 20
Script: {instanceID: 0}
- Class: 21
Script: {instanceID: 0}
- Class: 23
Script: {instanceID: 0}
- Class: 28
Script: {instanceID: 0}
- Class: 33
Script: {instanceID: 0}
- Class: 43
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
- Class: 81
Script: {instanceID: 0}
- Class: 89
Script: {instanceID: 0}
- Class: 104
Script: {instanceID: 0}
- Class: 108
Script: {instanceID: 0}
- Class: 114
Script: {fileID: 11500000, guid: f2b4ed9184e2de0458023175f84932e4, type: 3}
- Class: 115
Script: {instanceID: 0}
- Class: 135
Script: {instanceID: 0}
- Class: 157
Script: {instanceID: 0}
- Class: 196
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Scenes/Main.unity
Dependencies:
- "F:/UnityHigh-paying job classes/3-Advanced cases and techniques/AssetBundle\u5165\u95E8\u5230\u638C\u63E1/AssetBundleProj/AssetBundles/scene/wall.unity3d"
字段信息 | 字段含义 |
---|---|
ManifestFileVersion | 所属的版本号 |
CRC | 所用的校验码,可用于校验数据是否正确,在下载时可以使用 |
Assets | 所包含的资源名,可以在这里看到资源包的内容,如Assets/Scenes/Main.unity则表示里面有Main.unity资源,为一个场景资源 |
Dependencies | 资源包的依赖包所在路径 |
以上就是AB包打包后的内容介绍了。
1.3 Build的压缩方式介绍
BuildAssetBundleOptions
1.BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载
时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。
使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,
一旦它被下载了之后,它会使用LZ4算法保存到本地上。
BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。
2.AssetBundle的加载与资源的读取
AssetBundle包打包好了以后,我们就需要能够加载AB包了,这儿总共有四种加载AB包的方式:
1,AssetBundle.LoadFromMemory
2,AssetBundle.LoadFromFile
3,WWW.LoadFromCacheOrDownload
4,UnityWebRequest
下面将一一介绍:
假设我加载 AssetBundles/cubewall.unity3d资源包里面的CubeWall游戏物体,类型是GameObject,各个加载方式如下:
2.1 AssetBundle.LoadFromMemory
从内存加载AB包,是从本地进行加载的
//同步加载
void LoadABFromMemory()
{
string path = "AssetBundles/cubewall.unity3d";//加载的路径
//参数:读取到的AB包的内容的字节数组,为byte[]类型
AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
//异步加载
IEnumerator LoadABFromMemoryAsync()
{
string path = "AssetBundles/cubewall.unity3d";//加载的路径
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
yield return request;
AssetBundle ab = request.assetBundle;
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
2.2 AssetBundle.LoadFromFile
与2.1类似,也是从本地加载,根据路径加载
//同步加载
void LoadABFromFile()
{
string path = "AssetBundles/cubewall.unity3d";//加载的路径
//参数:AB包所在路径
AssetBundle ab = AssetBundle.LoadFromFile(path);
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
//异步加载
IEnumerator LoadABFromFileAsync()
{
string path = "AssetBundles/cubewall.unity3d";//加载的路径
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);
yield return request;
AssetBundle ab = request.assetBundle;
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
2.3 WWW.LoadFromCacheOrDownload
可下载读取网络上的AB包,也可以读取本地的AB包
IEnumerator LoadABFormWWWCaching()
{
//首先判断缓存是否准备好
while (Caching.ready == false)
{
yield return null;
}
string path = "AssetBundles/cubewall.unity3d";
//本地完整路径,注意,前面需要加上"file://"或"file:///"
string localFilePath = @"file:/E:\Unity Project Workspace\AssetBundleProject\" + path;
//网站上的路径uri
string netFilePath = @"http://localhost/" + path;
//假设从网站下载,第一个参数为路径,第二个参数为指定的版本号
WWW www = WWW.LoadFromCacheOrDownload(netFilePath, 1);
yield return www;
if (string.IsNullOrEmpty(www.error) == false)
{
Debug.Log(www.error);
yield break;
}
AssetBundle ab = www.assetBundle;
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
2.4 UnityWebRequest
与2.3类似,可下载读取网络上的AB包,也可以读取本地的AB包
IEnumerator LoadABFromUnityWebRequest()
{
string path = "AssetBundles/cubewall.unity3d";
//本地完整路径,注意,前面需要加上"file://"或"file:///"
string localFilePath = @"file:/E:\Unity Project Workspace\AssetBundleProject\" + path;
//网站上的路径uri
string netFilePath = @"http://localhost/" + path;
//假设从网站下载,第一个参数为路径,第二个参数为指定的版本号
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(netFilePath);
yield return request.SendWebRequest();
//AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
//使用里面的资源
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
}
3.AssetBundleManifest的相关操作
AssetBundleManifest即整个AB包的文件夹对应的manifest配置文件,可以获得与AB包对应的配置信息
//打包的目录文件夹对应的AB包
AssetBundle manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
//获取该AB包对应的manifest文件,注意
AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
//输出该manifest文件下的所有AB包的名字
foreach(string name in manifest.GetAllAssetBundles())
{
print(name);
}
//获取cubewall.unity3d资源包所有的依赖包路径
string[] strs = manifest.GetAllDependencies("cubewall.unity3d");
//输出并加载cubewall.unity3d资源包的依赖包
foreach (string name in strs)
{
print(name);
AssetBundle.LoadFromFile("AssetBundles/" + name);
}
4.AssetBundle的卸载
当所加载的AB包不再使用时,为了留出更多的内存空间,需要对不使用的AB包进行卸载。主要是通过AssetBundle.Unload函数进行卸载,但是根据参数有些差别。
1、AssetBundle.Unload(true):卸载所有资源,即使有资源被使用着也会卸载
适用的场景:
1)在关切切换、场景切换
2)资源没被用的时候调用
2、AssetBundle.Unload(false)卸载所有没用被使用的资源,正在使用的资源不会被卸载
个别资源怎么卸载:
1)通过 Resources.UnloadUnusedAssets.
2)场景切换的时候
5.AssetBundle浏览工具
这个工具可以很方便的让你在项目中浏览你所有设置的AB包,AB包的大小,AB包的内容,还可以查看项目外的其他AB包,帮助你打AB包。
github:Unity Asset Bundle Browser tool
总结
以上就是今天要讲的内容,本文介绍了AssetBundle包的创建、使用、加载和卸载等整个流程,AB包为我们实现资源的更新做好了准备,是热更新中的一个重要的环节。