AssetBundle简介

AssetBundle是Unity支持的一种文件储存格式,也是Unity官方推荐的资源存储与更新方式,它可以对资源(Asset)进行压缩,分组打包,动态加载,以及实现热更新,但是AssetBundle无法对Unity脚本进行热更新。(因此通过Lua来进行热更行)
至于为什么,这篇文章说的挺详细了:https://www.jianshu.com/p/71fffc9a9cac

在Unity的5.3版本时,简化了AssetBundle的打包方式,只留下了一个API与寥寥几个设置参数,而之前最让人头痛的资源依赖管理,也被默认进行处理。 而在每个Asset文件的Inspector面板上都会多出一个Asset Labels的设定栏:

  • AssetBundle Name:需要将此资源打包的AssetBundle名称
  • AssetBundle Variant:需要将此资源打包的AssetBundle的扩展名
    Variant:
    Variant是5.3以后新添加的一个概念,这个值其实是一个尾缀,添加在对应AssetBundle的名称之后,如:ddzgame.hd,hd就是Variant(从此以后AssetBundle的尾缀已经跟其文件类型本身没有任何联系了)。
    它主要用在不同版本资源的使用和动态替换AssetBundle。它被用来支持定制化的参数。与预定义宏类似,它可以对一个单独对象重映射项目中不同的资源。这样就可以灵活控制语言、地区、或者用户偏好。AssetBundle Variant相同的AssetBundle之间将有共同的内部id。通过设置Variant变量,可以实现定制化的资源控制。可以使用Variant区分了相同资源的不同版本,所以它可以为同一个资源提供不同的解决方案。

AssetBundle相关操作

自动打包脚本

从以上可知,如果需要一个一个的对资源设置AssetBundle Name与Variant实在太过繁琐与麻烦,也可能出现纰漏,好在可以通过脚本去批量设置这两个参数。(脚本放到Unity的Editor文件夹下)

1
2
3
4
5
//path是资源在Assets下的路径(eg: Assets/.../.....)   
AssetImporter assetImporter = AssetImporter.GetAtPath("path");
//设置AssetBundle Name与Variant
assetImporter.assetBundleName = "AssetbundleName";
assetImporter.assetBundleVariant = "AssetbundleVariant";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[MenuItem("AssetsBundle/Build AssetBundle")]   
static public void BuildAssetBundle()
{
AssetImporter asserImporter = AssetImporter.GetAtPath("Assets/Sources/Player1.prefab");
asserImporter.assetBundleName = "player";
asserImporter.assetBundleVariant = "prefab";

//将ab资源打包的当前工程的AssetBundles文件夹下(与Assets同级)
if(!Directory.Exists("AssetBundles"))
{
Directory.CreateDirectory("AssetBundles");
}
BuildPipeline.BuildAssetBundles("AssetBundles", BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh();
}

对Scene的打包
Scene打包跟资源打包无异,唯一需要注意的是:Scene只能与Scene打入同一个AssetBundle内,而无法与其他资源打入同一个AssetBundle。
AssetBundle内的Scene需要在AssetBundle加载后,通过SceneManager来加载。

压缩方式

  1. LZMA(Ziv-Markov chain algorithm)格式
    Unity打包成AssetBundle时的默认格式,会将序列化数据压缩成LZMA流,使用时需要整体解包。优点是打包后体积小,缺点是解包时间长,且占用内存。
  2. LZ4格式
    5.3新版本添加的压缩格式,压缩率不及LZMA,但是不需要整体解压。LZ4是基于chunk的算法,加载对象时只有响应的chunk会被解压。

    压缩格式在打包时通过AssetBundleOption参数选择。

AssetBundle资源加载

使用 WWW 或者 AssetBundle 相关 API 加载,其中 AssetBundle 的 API 只能进行本地加载。
AssetBundle.LoadfromMemory(byte[] bytes)用来对加密的Assetbundle进行读取,可以结合WWW使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BuileAsset : MonoBehaviour {    
//资源地址(Player.prefab是我的资源包的名称)
private string path = "File://F:/myUnityProject/AssetBundle/AssetBundles/Player.prefab";

IEnumerator Start()
{
WWW www = new WWW(path);
yield return www;
if (www == null)
{
Debug.Log("路径内容为空");
}
else
{
AssetBundle asset = www.assetBundle;
Object[] obj = asset.LoadAllAssets<GameObject>();
//实例化资源包中的游戏物体
foreach (var value in obj)
{
Instantiate(value);
}
www.Dispose();
}
}

AssetBundle资源卸载

1
AssetBundle.Unload(bool unloadAllLoadedObjects);

AssetBundle唯一的一个卸载函数,传入的参数用来选择是否将已经从此AssetBundle中加载的资源一起卸载。另外,已经从AssetBundle中加载的资源可以通过Resources.UnloadAsset(Object)卸载。不过通过Resources.UnloadUnusedAssets()卸载从AssetBundle加载的资源时,要先将AssetBundle卸载后才能生效。


 评论