目录
2️⃣ AssetBundle.CreateFromFile
🟥 下载AssetBundle
Unity提供了两种方式从服务器下载AssetBundle文件:
1、非缓存机制
2、缓存机制
1️⃣ 非缓存机制
通过创建一个WWW实例来对AssetBundle文件进行下载。下载后的AssetBundle文件将不会保存到Unity引擎特定的缓存区。下面是使用AssetBundle文件的代码:
IEnumerator Start()
{
//开始从指定的URL下载
WWW www = new WWW("url");
//等待下载完成
yield return www;
}
2️⃣ 缓存机制
通过WWW.LoadfromCacheorDownload接口下载AssetBundle文件。下载后的AssetBundle文件将自动保存到Unity引擎特定的缓存区中,该方法是Unity推荐的文件下载方式。
该接口在下载AssetBundle时,会先根据版本号在本地缓存区查找该文件,看其之前是否下载过。如果下载过,则直接从缓存区读取进来;如果没有,则从服务器进行下载。这样的优点是:可以节省AssetBundle文件的下载时间,提高游戏资源载入速度。
注意:Unity提供的默认缓存大小是根据发布平台不同而不同的。
Web Player上的网页游戏默认缓存50M
iOS/Android默认4GB
开发商可通过购买由Unity提供的Caching License来增大网页平台上的缓存大小,该授权可极大提高网页游戏运行流畅度。
IEnumerator Start()
{
//开始从指定的URL下载
WWW www = WWW.LoadFromCacheOrDownload("URL",5);
//等待下载完成
yield return www;
}
🟧 加载AssetBundle
当把AssetBundle文件从服务器下载到本地后,需要将其加载到内存中并创建AssetBundle文件内存对象。
以下是两种加载AssetBundle文件的方式(Unity原提供4个)
1️⃣ WWW.assetbundle
通过WWW.assetbundle属性创建一个AssetBundle文件的内存对象。
IEnumerator Start()
{
//开始从指定的URL下载
WWW www = WWW.LoadFromCacheOrDownload("URL",5);
//等待下载完成
yield return www;
if (www.error != null)
{
Debug.Log(www.error);
yield return www;
}
AssetBundle myLoadedAssetBundle = www.assetBundle;
}
2️⃣ AssetBundle.CreateFromFile
AssetBundle.CreateFromFile的完整定义为:
public static AssetBundle CreateFromFile(string path);
通过该接口,可以从磁盘文件创建一个AssetBundle文件的内存对象。
该方法仅支持压缩格式的AssetBundle,即在创建AssetBundle时必须使用UncompressedAssetBundle选项。
注意:如果在AssetBundle之间存在依赖关系,要先加载总的Manifest文件,通过Manifest文件加载对应的依赖文件,然后再加载要加载的AssetBundle。
例:在加载名为“test”的AssetBundle时,需要先加载它的依赖文件“m1”,然后再加载“test”。代码如下:
using System.Collections;
using UnityEngine;
public class Skode_AssetBundle_Test : MonoBehaviour
{
//总的Manifest文件名称
public string manifestName = "AssetBundles";
//要加载的AssetBundle名称
public string assetBundleName = "test";
IEnumerator Start()
{
//AssetBundle所在的路径
string assetBundlePath = "file://" + Application.dataPath + "/AssetBundles/";
//Manifest文件
string manifestPath = assetBundlePath + manifestName;
//首先加载Manifest文件:下载AssetBundle文件
WWW wwwManifest = WWW.LoadFromCacheOrDownload(manifestPath, 0);
yield return wwwManifest;
if (wwwManifest.error == null)
{
//创建一个AssetBundle文件的内存对象
AssetBundle manifestBundle = wwwManifest.assetBundle;
//AssetBundleManifest:Manifest for all the AssetBundles in the build.
//.LoadAsset(string name):这种方式是使用资源名称作为参数来加载需要的资源,
//例如AssetBundle包含了一个名为CubeObj的立方体,
//那么就可以使用AssetBundle.LoadAsset(“CubeObj”)来返回资源。
AssetBundleManifest manifest = (AssetBundleManifest)manifestBundle.LoadAsset("AssetBundleManifest");
manifestBundle.Unload(false);
//获取要加载的AssetBundle的依赖文件列表
string[] dependentAssetBundles = manifest.GetAllDependencies(assetBundleName);
AssetBundle[] abs = new AssetBundle[dependentAssetBundles.Length];
for (int i = 0; i < dependentAssetBundles.Length; i++)
{
//加载所有的依赖文件
WWW www = WWW.LoadFromCacheOrDownload(assetBundlePath + dependentAssetBundles[i], 0);
yield return www;
abs[i] = www.assetBundle;
}
//加载需要的文件
WWW www2 = WWW.LoadFromCacheOrDownload(assetBundlePath + assetBundleName, 0);
yield return www2;
AssetBundle assetBundle = www2.assetBundle;
}
else
Debug.Log(wwwManifest.error);
}
}
🟨 从AssetBundle中加载Assets
当AssetBundle文件加载完成后,就可以将它所包含的Assets加载到内存中。以下是Unity提供的6种API加载方式。
AssetBundle.LoadAsset | 该接口可以通过名字将AssetBundle文件中包含对应Asset名称同步加载到内存,也可以通过参数来指定加载Asset的类型。 |
AssetBundle.LoadAssetAsync | 与上作用相同。不同的是:该接口是对Asset进行异步加载,即加载时主线程可以继续执行。 |
AssetBundle.LoadAllAssets | 该接口用来一次性同步加载AssetBundle文件中的所有Assets,同.LoadAsset一样,可通过指定加载Asset的类型来选择性加载Assets。 |
AssetBundle.LoadAllAssetsAsync | 该接口用来一次性异步加载AssetBundle文件中的所有Assets。 |
AssetBundle.LoadAssetWithSubAssets | 该接口可以通过名字同步加载AssetBundle文件中的Assets的子Assets,同.LoadAsset一样,可以通过指定加载Asset的类型来选择性加载Assets。 |
AssetBundle.LoadAssetWithSubAssetsAsync | 该接口可以通过名字异步即在AssetBundle文件中的Assets的子Assets。 |
示例:
以下是使用了AssetBundle.LoadAsync接口从AssetBundle中加载Asset的示例
IEnumerator Start()
{
WWW www = WWW.LoadFromCacheOrDownload(url, 1);
yield return www;
//取得AssetBundle
AssetBundle bundle = www.assetBundle;
//异步加载对象
AssetBundleRequest request = bundle.LoadAssetAsync("myObject", typeof(GameObject));
//等待异步加载完成
yield return request;
//获得加载对象的引用
GameObject obj = request.asset as GameObject;
//从内存中卸载AssetBundle
bundle.Unload(false);
}
🟩 从场景AssetBundle中加载Assets
以上介绍了怎样从普通AssetBundle文件中加载Assets。当从场景文件生成的AssetBundle中加载Assets时,用户必须通过Application.LoadLevel等接口来加载场景,分别如下:
Application.LoadLevel | 该接口可以通过名字或者索引载入AssetBundle文件中包含的对应场景。当加载新场景时,所有之前加载的GameObject都会被销毁 |
Application.LoadLevelAsync | 该接口作用同上,不同的是该接口是对场景进行异步加载,即加载时主线程可以继续执行 |
Application.LoadLevelAdditive | 不同于Application.LoadLevel的是,它并不销毁之前加载的GameObject |
Application.LoadLevelAdditiveAsync | 该接口作用同上.LoadLevel,不同的是该接口对场景进行异步加载,即加载主线程时可以继续执行 |
以下是使用Application.LoadLevelAsync接口异步加载的例子,代码如下:
using System.Collections;
using UnityEngine;
public class Skode_AssetBundle_Test : MonoBehaviour
{
//场景文件名称
public string sceneAssetBundle;
//场景名称
public string sceneName;
IEnumerator Start()
{
//场景AssetBundle路径
string path = "file://" + Application.dataPath + "/AssetBundles/" + sceneAssetBundle;
WWW www = WWW.LoadFromCacheOrDownload(path, 1);
yield return www;
if (www.error == null)
{
AssetBundle ab = www.assetBundle;
AsyncOperation async = Application.LoadLevelAsync(sceneName);
yield return async;
}
else
Debug.Log(www.error);
}
}
🟦 AssetBundle Variant的使用
美 [ˈveriənt]
AssetBundle Variant通过AssetBundle用来实现Virtual Assets,和不同版本资源的使用,最终达到在运行时动态替换AssetBundle。
AssetBundle名称相同,但不同的是,AssetBundle Variant的AssetBundle之间将有共同的内部id,所以它们可以之间可以任意切换。
用户可以通过以下方式设置AssetBundle Variant
1、通过AssetBundle的UI来设置
2、AssetImporter.assetBundleVariant,代码如下
AssetImporter assetImporter = new AssetImporter();
assetImporter.assetBundleVariant = "hd";
3、AssetBundleBuild.assetBundleVariant
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
assetBundleBuild.assetBundleVariant = "hd";
AssetBundle Variant会用于AssetBundle的扩展名中,例如:
AssetImporter assetImporter = new AssetImporter();
assetImporter.assetBundleName = "myassets";
assetImporter.assetBundleVariant = "hd";
//最终AssetBundle name为“myassets.hd”
🟪 卸载AssetBundle
使用AssetBundle.Unload接口来卸载,完整定义如下:
// 摘要:
// Unloads all assets in the bundle.
public void Unload(bool unloadAllLoadedObjects);
该接口有个bool参数,如果把参数设为false,则调用该接口时只会卸载AssetBundle对象本身,并不会对从AssetBundle中加载的Assets有任何影响;如果设置为true,则不仅会卸载AssetBundle,还会卸载其加载的Assets,无论他们是否还在被使用。
推荐设置为false,只有当很明确知道从AssetBundle加载的Assets不会被使用时,才将参数设置为true。
大家还有什么问题,欢迎在下方留言!
如果你有 技术的问题 或 项目开发
都可以加下方联系方式
和我聊一聊你的故事🧡