Unity学习日记:AssetBundle工作流程之下载与加载资源
一、下载
unity提供了两种方式从服务器上动态下载AssetBundle文件。
(1)非缓存机制:通过创建一个WWW的实例来对AssetBundle文件进行下载,但是下载后并不会保存到Unity特定的缓存区。
语法:WWW. LoadFromCacheOrDownload(string url, int version, uint crc = 0);
URL :如果资源包在缓存不存在,那么从URL来下载AssetBundle。必须是'%'转义的;
version:AssetBundle的版本。如果已下载的带有相同参数的版本,该文件仅从硬盘加载。通过你的应用程序递增版本号,能强制缓存从URL下载一个新的AssetBunlde拷贝。
uint crc = 0:可选,未压缩内容的CRC-32校验。如果为非零,则内容会在加载之前比较校验值,如果不匹配给出错误。你可以用这个来避免从下载或用户在硬盘的缓存文件篡改导致数据损坏。如果CRC不匹配,Unity将尝试重新下载数据,如果CRC在服务器不匹配将会报错。查看返回的错误字符串,查看正确的CRC值用于AssetBundle。
代码如下:
IEnumerator start() { WWW www=new WWW(url);//从指定的URL下载AssetBundle yield return www;//等待下载完成 }(2)缓存机制:通过WWW.LoadFromCacheOrDownload接口下载AssetBundle文件,下载后将会自动被保存在Unity特定的缓存区内,Unity推荐此种方法。另,在下载文件前,此接口会现根据版本号在本地缓存区查找该文件,若之前下载过,则直接从缓存区读取进来,若没有下载过,则按照指定的路径从服务器进行下载,这样可以节省下载时间,提高游戏载入速度。unity提供的缓存大小根据发布的平台不同而不同,发布到Web Player的网页游戏,默认缓存50MB,发布到PC、安卓、IOS的游戏默认缓存为4GB。可以购买许可以提高缓存大小。
IEnumaretor start() { WWW www=WWW.LoadFromCacheOrDownload(URL,5);//开始检查内存或者从指定的URL位置下载 yield return www;//等待下载完成 }
二、加载
虽然unity提供的两种方式从服务器上动态下载了AssetBundle文件,但是我们还需要通过加载的方式才能读取其中的信息和数据。unity提供了四种方式来完成加载AssetBundle。
(1)WWW.assetbundle
IEnumerator start() { WWW www=WWW.LoadFromCacheOrDownload(URL,5); yield return www; if(www.error!=null) { Debug.Log(www.error); yield break; } AssetBundle myloadassetbundle=WWW.assetbundle; }
(2)AssetBundle.CreatFromFile:可以从磁盘文件创建一个AssetBundle的内存对象,这个函数仅支持未压缩的AssetBundle,即在创建AssetBundle时使用UncompressdAssetBundle选项。
语法:AssetBundle.CreateFromFile(string path);
path:assetbundle在本地磁盘的路径
(3)AssetBundle.CreatFromMemory:从内存区创建异步AssetBundle内存区域,例如当用户对AssetBundle进行加密时,可以先调用解密算法返回解密后的数据流,在通过AssetBundle.CreatFromMemory从数据流创建AssetBundle对象。
IEnumerator start() { var www=WWW.LoadFromCacheOrDownload(url,5); yield return www; AssetBundleCreateRequest assetbundlecreaterequest=AssetBundle.CreatFromMemory(www.bytes); yield return assetbundlecreaterequest; AssetBundle assetbundle=assetbundlecreaterequest.assetbundle; }
(4)AssetBundle.CreatFromMemoryImmediate:从内存区同步创建资源包,应用这个方法从字节数组创建一个资源包。当你想在自己的系统中下载资源包而不是用WWW类下载,或者当你已经下载好了加密数据,并且需要从未加密的数据创建资源包时使用这个方法是很有效的。与AssetBundle.CreateFromMemory相比较,这个版本是同步的并且直到资源包对象被创建完毕才返回。
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { IEnumerator Start() { WWW www = new WWW("http://myserver/myBundle.unity3d"); yield return www; AssetBundle assetBundle = AssetBundle.CreateFromMemoryImmediate(www.bytes); } }当资源包之间有依赖关系时,需要先加载对应的依赖文件,才能再加载我们需要的那个AssetBundle。当我们生成AssetBundle时,会在同一个文件夹下生成与AssetBundle同名的Manifest文件,并且会生成与此文件夹同名的AssetBundle文件和Manifest文件。这些Manifest文件虽然包含着可供我们查看的资源包之间的依赖信息,但是它们只是unity在生成AssetBundle时用于排至他们的文件,并不会在游戏发布时一同发布,相反,所生成的所有的资源包之间的依赖关系都承载于这个于文件夹同名的AssetBundle文件里,如要取得所有资源包之间的依赖关系,就要先下载这个与文件夹同名的AssetBundle,然后以LoadAsset的方式提取,最后在转化为AssetBundleManifest。
using UnityEngine; using system.Collection; public class LoadAsset:MonoBehaviour { public string manifestAssetBundleName=“AssetBundle”;//承载所有资源包依赖信息的与文件夹同名的那个AssetBundle的名称 public string assetbundleName=“test”;//想要加载的AssetBundle的名称 IEnumerator start() { string assetbundlePath=“file://”+Application.datapath+“/AssetBundle/”;//要加载的AssetBundle所在的文件夹路径 string manifestAssetBundlePath=assetbundlePath+manifestAssetBundleName;//承载所有资源包依赖信息的与文件夹同名的那个AssetBundle的路径 WWW wwwmanifestAssetBundle=WWW.LoadFromCacheOrDownload(manifestAssetBundlePath,0);//下载包含依赖关系的AssetBundle yield return wwwmanifestAssetBundle;//等待下载完成 AssetBundle manifestAssetBundle= wwwmanifestAssetBundle.assetbundle;//加载包含依赖关系的AssetBundle AssetBundleManifest manifest=(AssetBundleManifest)manifestAssetBundle.LoadAsset(“AssetBundleManifest”);//从AssetBundle中提取包含依赖关系的manifest文件,并转换成AssetBundleManifest类型。 manifestAssetBundle.Unload(false); //获取依赖关系列表 string[] dependAssetBundles=manifest.GetAllDependencies(assetbundleName); AssetBundle[] abs=new AssetBundle[dependAssetBundles.Length]; for(i=0;i<dependAssetBundles.Length;i++) { //加载所有依赖文件 WWW www=WWW.LoadFromCacheOrDownload(assetbundlePath+dependAssetBundles[i],0); yield return www; abs[i]=www.assetbundle; } //加载想要加载的那个AssetBundle WWW wwwtest=WWW.LoadFromCacheOrDownload(assetbundlePath+assetbundleName,0); yield return wwwtest; AssetBundle test=wwwtest.assetbundle; } }