Unity网络交互☀️AssetBundle二、:如何下载、加载与卸载AssetBundle

发布于:2022-12-15 ⋅ 阅读:(900) ⋅ 点赞:(0)

在这里插入图片描述

目录

🟥 下载AssetBundle

1️⃣ 非缓存机制

2️⃣ 缓存机制

🟧 加载AssetBundle

1️⃣ WWW.assetbundle

2️⃣ AssetBundle.CreateFromFile

🟨 从AssetBundle中加载Assets

🟩 从场景AssetBundle中加载Assets

🟦 AssetBundle Variant的使用

🟪 卸载AssetBundle


🟥 下载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。

大家还有什么问题,欢迎在下方留言!


 

在这里插入图片描述


如果你有 技术的问题 或 项目开发

都可以加下方联系方式

和我聊一聊你的故事🧡


网站公告

今日签到

点亮在社区的每一天
去签到