一、定义
AssetBundle是一种包含特定平台非代码资源的存档文件。例如模型、贴图、预制、音频文件、甚至是整个场景等。资源使用Unity提供的一种用于存储资源的压缩格式打包成AssetBundle.可在运行时候动态加载。
使用AssetBundle动态加载资源首先要获取AssetBundle对象,第二步才是从AssetBundle中加载目标资源,然后再实例化目标资源。
二、AssetBundle的具体开发流程
一般情况下AssetBundle的具体开发流程如下:
(1)创建Asset bundle,开发者在unity编辑器中通过脚本将所需要的资源打包成AssetBundle文件。
(2)上传服务器。开发者将打包好的AssetBundle文件上传至服务器中。使得游戏客户端能够获取当前的资源,进行游戏的更新。
(3)下载AssetBundle,首先将其下载到本地设备中,然后再通过AsstBudle的加载模块将资源加到游戏之中。
(4)加载,通过Unity提供的API可以加载资源里面包含的模型、纹理图、音频、动画、场景等来更新游戏客户端。
(5)卸载AssetBundle,卸载之后可以节省内存资源,并且要保证资源的正常更新。
三、创建AssetBundle
在Inspector面板设置包名
然后通过Unity的API打包成AssetBundle
public class AssetBundleEditor
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
BuildPipeline.BuildAssetBundles("Assets/StreamingAssets", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
}
}
打包出来会有2个文件,如下图所示。
在选择BuildAssetBundleOptions打包资源压缩选择
Unity3D引擎为我们提供了三种压缩策略来处理AssetBundle的压缩,即:
1、LZMA格式
2、LZ4格式
3、不压缩
LZMA格式:是一种高压缩比压缩方式,出来的包体体积小,但是使用时需要先解压,而且解压时间长。
LZ4格式:压缩比一般,出来的包体体积较大,使用时也需要解压,但是解压时间短。
不压缩:体积大,但是使用时,不需要解压。
四、加载AssetBundle对象
1、通过WWW方式
1.1、public WWW(string url),直接调用WWW类的构造函数
构造WWW对象的过程中会加载Bundle文件并返回一个WWW对象,完成后会在内存中创建较大的WebStream(解压后的内容,通常为原Bundle文件的4~5倍大小,纹理资源比例可能更大),因此后续的AssetBundle.LoadAsset可以直接在内存中进行。
unity示例代码块
public class ExampleClass : MonoBehaviour
{
IEnumerator Start()
{
using (WWW www = new WWW("http://myserver/myBundle.unity3d"))
{
yield return www;
// Get the designated main asset and instantiate it.
Instantiate(www.assetBundle.mainAsset);
}
}
}
1.2、WWW.LoadFromCacheOrDownload
调用该方法同样会加载Bundle文件同时返回一个WWW对象,和上一个直接调用WWW的构造函数的区别在于该方法会将解压形式的Bundle内容存入磁盘中作为缓存(如果该Bundle已在缓存中,则省去这一步),完成后只会在内存中创建较小的SerializedFile,而后续的AssetBundle.LoadAsset需要通过IO从磁盘中的缓存获取。
unity示例代码块
public class LoadFromCacheOrDownloadExample : MonoBehaviour
{
IEnumerator Start()
{
while (!Caching.ready)
yield return null;
using (var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield return null;
}
var myLoadedAssetBundle = www.assetBundle;
var asset = myLoadedAssetBundle.mainAsset;
}
}
}
2、API–AssetBundle CreateFromFile(string path);
通过未压缩的Bundle文件,同步创建AssetBundle对象,这是最快的创建方式。创建完成后只会在内存中创建较小的SerializedFile,而后续的AssetBundle.Load需要通过IO从磁盘中获取。加载时候选择未压缩即可,Unity2017新版本也可以加载压缩的AssetBundle.
void TestUnloadFun()
{
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle.data"));//AssetBundle.LoadFromFile( Application.dataPath+ "/StreamingAssets/myassetBundle.data")
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("MyObjectPerfab");
Instantiate(prefab);
myLoadedAssetBundle.Unload(false);
}
3、API–AssetBundle.CreateFromMemory
通过Bundle的二进制数据,异步创建AssetBundle对象。
完成后会在内存中创建较大的WebStream。调用时,Bundle的解压是异步进行的,因此对于未压缩的Bundle文件,该接口等价于AssetBundle.CreateFromMemoryImmediate.具体参考unity官方示例。
接口对比:new WWW与WWW.LoadFromCacheOrDownload
前者的优势
● 后续的Load操作在内存中进行,相比后者的IO操作开销更小;
● 不形成缓存文件,而后者则需要额外的磁盘空间存放缓存;
● 能通过WWW.texture,WWW.bytes,WWW.audioClip等接口直接加载外部资源,而后者只能用于加载AssetBundle;
前者的劣势
● 每次加载都涉及到解压操作,而后者在第二次加载时就省去了解压的开销;
● 在内存中会有较大的WebStream,而后者在内存中只有通常较小的SerializedFile。(此项为一般情况,但并不绝对,对于序列化信息较多的Prefab,很可能出现SerializedFile比WebStream更大的情况)
五、加载目标资源
常用方法
LoadAsset:从资源包中加载指定的资源
LoadAllAsset:加载当前资源包中所有的资源
LoadAssetAsync:从资源包中异步加载资源
六、资源卸载
使用Unload方法。
该方法会卸载运行时内存中包含在bundle中的所有资源。
当传入的参数为true,则不仅仅内存中的AssetBundle对象包含的资源会被销毁。根据这些资源实例化而来的游戏内的对象也会销毁。
当传入的参数为false,则仅仅销毁内存中的AssetBundle对象包含的资源。
参考链接:https://zhuanlan.zhihu.com/p/80854264