一、AB包是什么
AB包全名AssetBundle(资源包)。是一种Unity提供的用于存放资源的包。通过将资源分布在不同的AB包中可以最大程度地减少运行时的内存压力,并且可以有选择地加载内容。
二、为什么要用AB包
主要原因,就是用作资源热更新,以及对应用包体的减负
三、有没有现成的打AB包的插件
有官方出过一个插件《AssetBundle Browser》,该插件在Github上,下载导入就可以使用,我这边就不做过多的介绍了。
四、能不能自己编写打AB包功能
能,但是这需要一定的编辑器扩展知识,下面会放上简单的代码,实现打AB包,以及加载AB包。
首先自己编写编辑器扩展,我们需要一个文件夹和一个命名空间以及一个预编译,分别是:
文件夹:Editor,在Assets文件夹下创建一个文件夹,叫这个名称,这个名称在Unity中是特殊的,放在里面的脚本都是用来编写编辑器扩展的代码,最后发布也不会把该文件中的代码发布出去。
命名空间:UnityEditor,在Unity中编辑器是一套代码,应用开发功能是一套代码,分别编辑器的是UnityEditor,应用功能是UnityEngine,发布应用只会把UnityEngine的代码发布到应用中,如果在需要发布的代码中应用UnityEditor发布时会报异常,导致发布失败。
预编译:UNITY_EDITOR,当我们要编写编辑器扩展,如果必须在需要发布的代码中编写时,那么可以在编辑器扩展的这部分代码加上UNITY_EDITOR预编译头,那么发布应用时会自动裁剪掉,就不会影响发布导致发布失败。
说了这么多,就直接开始上代码吧,首先创建一个编辑器扩展的按钮,就前面说的在Assets文件夹下创建一个Editor文件夹,创建一个脚本AssetBundleBrowser
接着就是创建一个按钮(如下图),我们在脚本中编写一个静态方法,然后增加上MenuItem字段即可,字段参数是这个按钮的名称,如果加上/可以增加多级菜单
代码如下:
接着就是调用Unity中提供的打包AB的方法(如下),
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
第一个参数:是打包的输出路径(路径到文件夹即可,不需要增加文件名)
第二个参数:构建选项,默认选项(None),具体的建议查看官方文档,下图也有参数介绍,但是每个版本的他会有调整,建议还是查看官方文档
第三个参数:是打包平台,每个平台的AB包输出不一致,因此需要区分不同平台打AB包。
完整代码:
using UnityEditor;
using UnityEngine;
public class AssetBundleBrowser
{
[MenuItem("AssetBundle/Build AssetBundle")]
public static void BuildAssetBundle()
{
// 定义Ab包的输出目录
string assetBundleDirectory = "Assets/AssetBundles";
// 检查目录是否存在,如果不存在则创建该目录
if (!System.IO.Directory.Exists(assetBundleDirectory))
{
System.IO.Directory.CreateDirectory(assetBundleDirectory);
}
// 使用BuildPipeline构建AssetBundles
// 参数1:输出目录
// 参数2:构建选项,这里使用默认选项(None)
// 参数3:目标平台,这里选择Windows平台
Debug.Log("开始打包");
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
Debug.Log("打包完成");
}
}
代码编写好后,接着就是设置需要打AB的资源,我们需要在Assets文件夹中选择资源,然后在Inspector面板的最下方就有设置AB包名称和后缀的地方,具体设置的名称,自行定义(点击下拉后点击new,就可以自行定义名称了,后缀也是)
设置完成后如下,然后去点击创建的按钮,就会开始打包,需要注意的一点是,你打AB包的平台,必须是你在UnityHub上已经安装了该平台的发布扩展。
等待打包完成之后,到设置的文件夹下,就能看到你设置名称和后缀的ab文件了,除了该文件还有个manifest后缀的文件,这个是ab包的配置,实际记载时可以不需要用到,因此如果资源更新也只要更新ab文件即可。
五、加载AB包
讲完打AB包后,就是加载AB包了,但是有一点需要注意,由于Unity版本更新会修改这部分引擎代码,因此建议什么版本打的AB包就用什么版本去加载,否则加载出来可能会有问题。之前碰到过材质丢失的现象。
加载AB包很简单,只需要调用LoadFromFile,就可以加载了,当然如果你是加载远端文件的,那么就是下载请求,获取到字节数组后也可以通过LoadFromMemory方法加载。
AssetBundle assetBundle = AssetBundle.LoadFromFile(path);//加载AssetBundle
AssetBundle.LoadFromMemory(data);//data是字节数组
如果加载的是场景到这一步,Load完就可以直接去加载场景了,记得使用完后调用Unload释放AB包,防止大量占用内存,这个根据项目自行管理。
但是如果是加载的其他文件或者预制体等,就还需要LoadAsset或者LoadAllAssets,类型根据你打包时对应有的组件获取文件类型设置。然后才能通过对应的GameObject创建实例。
AssetBundle assetBundle = AssetBundle.LoadFromFile(path);//加载AssetBundle
//对应名称的Asset
var obj = assetBundle.LoadAsset<GameObject>(name)
//或者加载全部Asset
var list = assetBundle.LoadAllAssets<GameObject>();
//读取需要的资源
GameObject obj = Instantiate(gameObject.transform);//加载prefab
到这里打包AssetBundle和加载AssetBundle都完成了,当然这里面还有一些更进一步的问题,例如按照上方的打包方式会打包所有设置了AssetBundle名称的资源,但如果资源热更时,只需要更新某个或者某几个资源该怎么操作?
后面我编写了一遍进阶版的文章,就是进一步的提升了资源打包工具的功能。可以选择只打包某个或某几个资源,同时文章最后会介绍怎么解决URP渲染管线时加载的资源shader丢失的解决方案。
文章可以查看《Unity中打可选择的AssetBundle,以及URP中加载AssetBundle包Shader丢失问题显示洋红色的解决方案》
优化后的AssetBundle打包工具截图如下: