是什么
AssetBundle是包含模型、材质、纹理、场景等资源的文件。是把unity资源按照一定的规则打包,然后这些资源可以上传的服务器,在游戏中可以下载这些资源,再把解包成资源。
打包上传服务器
分为两步:1.打包AssetBundles。2.上传AssetBundles到服务起。
下载解包
分为两步:1.下载AssetBundles到应用中。2.加载需要的资源从AssetBundles
怎么用
步骤在上面的介绍都可以清晰的看出来了,我们这里分为5个简单的步骤。
简单的工作流:
●在编辑器中组织和设置AssetBundles。
●打包AssetBundles。
●上传AssetBundles到外部存储。
●在运行时下载AssetBundles。
●加载AssetBundles中的资源。
下面我们来详细的看看每一个步骤具体怎么做。
在编辑器中组织和设置AssetBundles:
这里只需要设置名字与类别。
先在AssetBundle设置资源的AssetBundle的名字。这里这里设置名字时,设置二级菜单使用/斜杠编写名字例如environment/desert.
Paste_Image.png
名字后面还可以设置一个类别,叫作AssetBundle Variants,跟shader里面设置不同设备渲染算法不同一个道理,这个设置名称来区别加载那里一资源。比如说在好一点设备上可以加载高模不卡顿,而差一点的设备中只能加载低模才不卡顿,我们就可以使用这个来区别。这个也可用来做分包,不同版本包,最好的例子就是做多语言包。
打包AssetBundles:
然后再导出AssetBundle使用下面的代码。
[MenuItem("Assets/Build AssetBundles")]
private static void BuildAllAssetBUndles()
{
BuildPipeline.BuildAssetBundles("Assets/AssetBundles", BuildAssetBundleOptions.None,
BuildTarget.StandaloneOSXUniversal);
}
值得注意的是这里导出的路径是必须存在的,也就是这里的第一个参数。
第二个参数是可以设置压缩方式的,这里看看压缩有那些。
Asset Bundle 压缩分为三种:
1.LZMA:默认的压缩方式,特点是可以达到很小的容量,但是这样就会导致解压时会花更多的时间。设置为BuildAssetBundleOptions.None,作为DLCs的资源用这种压缩。
2.LZ4:5.3版本之后才有,压缩出来还是比较大容量,但是在加载使用时,不需要去解压缩,只需要校对一下即可。设置为BuildAssetBundleOptions.ChunkBasedCompression,加密资源,配置表,资源流等这些使用这种压缩。
3.不压缩:原始大小,加载快。设置为BuildAssetBundleOptions.UncompressedAssetBundle
当然还可以在这里设置一个条件,比如说不包含属性信息打包等。
第三个参数也就是设置打包到那个目标机型上去。
这里会生成两类文件,一个是Manifest,有一点像配置表的意思,它存储了打包资源的依赖文件的信息。这个依赖跟我们在unity中导出package包是一样的,他会把这个资源用到的其他资源记录下来。
在运行时下载AssetBundles:
这里有3种方式下载AssetBundles,通过名字我们就可以知道他们的区别:
1.无缓存:使用的是WWW object,也就是说使用的new WWW对象。例子如下:
using System;
using UnityEngine;
using System.Collections; class NonCachingLoadExample : MonoBehaviour {
public string BundleURL;
public string AssetName;
IEnumerator Start() {
// Download the file from the URL. It will not be saved in the Cache
using (WWW www = new WWW(BundleURL)) {
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}
2.有缓存:使用的是WWW.LoadFromCacheOrDownload。使用这个至少用4GB。
using System;
using UnityEngine;
using System.Collections;
public class CachingLoadExample : MonoBehaviour {
public string BundleURL;
public string AssetName;
public int version;
void Start() {
StartCoroutine (DownloadAndCache());
}
IEnumerator DownloadAndCache (){
// Wait for the Caching system to be ready
while (!Caching.ready)
yield return null;
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}
3.使用UnityWebRequest,这个可以取代www来使用,具体写法:
//string uri = @"file:///E:\Unity Project Workspace\AssetBundleProject\AssetBundles\cubewall.unity3d";
string uri = @"http://localhost/AssetBundles/cubewall.unity3d";
UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);
yield return request.Send();
//这里可以使用两种方式来获得AssetBundle
//AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
//使用里面的资源
GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
Instantiate(wallPrefab);
加载AssetBundles中的资源:
资源下载来了,这里像是Resource.Load的用法。我们可以使用三个方式来加载资源:
●AssetBundle.LoadAsset:直接加载
●AssetBundle.LoadAssetAsync:异步加载
●AssetBundle.LoadAllAssets:加载所有
这里的异步加载需要在加载大量资源或者资源容量大的时候使用。
这里有一个AssetBundle.Unload方法,是用来释放内存的,这个方法需要传入一个bool值,如果传入的是FALSE,这个AssetBundle就会被消除,但是从这个AssetBundle中加载出来的资源不会被删除。传入TRUE的话加载出来的资源也会被消除。在后面也可以使用Resource.UnLoadUnuseAssetBundle来卸载。
这里如果是依赖打包的,需要先加载共享资源包,然后再加载使用这个资源的预制物体这些。 这个加载顺序无所谓,但是在使用预制物体时,资源是要先加载出来的。这里的加载就是实例化出一个assetbundle对象。
我们可以直接加载总的生成的AssetBundles文件,再通过这个文件获得AssetBundleManifest依赖文件,获得这个打包文件的所有文件名字,然后根据名字来加载这个包里的文件。
var manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
var manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
foreach (var name in manifest.GetAllAssetBundles())
{
print(name);
}
string[] strs = manifest.GetAllDependencies("cubewall.unity3d");
foreach (string name in strs)
{
print(name);
AssetBundle.LoadFromFile("AssetBundles/" + name);
}
相关小记
分包策略
这里就是设置AssetBundle Variants这个,一些小策略有这些:
1.根据文件类型来分包,比如:贴图、声音这样的分类。
2.根据场景来分包,每有一个场景都设置一个包单独来控制。
3.根据物体的整理来分包,比如一个UI界面的预制体,这个预制体上用到的图片、脚本、shader等都打包在一起。
4.经常更新的资源放在一个包,不经常更新的资源放在一个包。
5.把共享资源打包成单独的包,这个也就是以来打包。
储存小原理
压缩区域指的是了chunk-base压缩(LZ4)或者stream-base压缩(LZMA)。
LZ4就是把资源平均分成很多个数据块,然后再把每个数据块单独压缩。使用这种压缩的话就是可以在运行时读取随机的数据消耗会很小,个人理解这里用这种压缩方式的一般是数据表之类的。
LZMA就是尽可能的压缩资源,但是读取的话只能序列读取。
网友评论