Unity AssetBundle 资源管理(2)--- 远程资源

上篇文章说到了 bundle的打包加载等一些功能

上篇文章传送门Unity AssetBundle 资源管理(1)--- 基础功能,包含标记、打包、加载、依赖和卸载-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_37302769/article/details/134559730

上篇文章只做了本地同步加载资源,对于Android和iOS平台则是需要吧bundle资源放入到 StreamingAssets 打入 包体内才行, 对于有些项目是想要吧资源放到远程的资源服务器上,等需要用的时候在下载到本地,这里在做一篇文章说明

1 部署资源服务器   

所谓资源服,就是可以吧我们的bundle资源上传上去,通过web链接可以直接下载,例如阿里云的OSS服务,这需要我们项目正式上线才用得到,至于开发或学的时候,我们搞一个本地的局域网服务器就行了,可以做这个事情的软件有很多,我就不一一介绍了,我用的软件是 nginx ,用法这里就不过多介绍了,自行查询资料吧

2 打包/上传资源

打包就不多说了,与上篇文章是一样的,只是需要吧打包好的资源放到资源服上去 ,为了方便管理,资源目录结构需与本地一致(web链接除外)

我这里运行nginx之后,texture的bundle目录就是  http://192.168.1.56/AssetBundle/Windows/texture

吧目录复制到浏览器的网址页 如果能成功下载到资源,则证明我们的资源服搭建成功了

.

3 资源下载

目录新版本的Unity已经基本舍弃了www类,推荐采用 UnityWebRequest 类下载,我这里选用的策略是下载bundle资源,放入内存,在同步加载资源,根据使用情况释放内存

看代码吧

字段  manifest储存、bundle缓存列表

 /// <summary>
    /// 它保存了各个AssetBundle的依赖信息
    /// </summary>
    private AssetBundleManifest abManifestAsync;
    private Dictionary<string, LoadedAssetBundle> abCacheAsync = new Dictionary<string, LoadedAssetBundle>();

函数:获取远程资源根目录

 //获取bundle远程目录
    public static string GetBundleRemotePath()
    {
        string path = $"http://192.168.1.56/AssetBundle/{GetPlatformName()}";
        return path;
    }

函数:加载 manifest

/// <summary>
    /// 加载Manifest文件 异步
    /// </summary>
    /// <returns></returns>
    private async Task LoadManifestAsync()
    {
        if (abManifestAsync == null)
        {
            string url = $"{GetBundleRemotePath()}/{GetPlatformName()}";
            UnityWebRequest www = UnityWebRequest.Get(url);
            UnityWebRequestAsyncOperation asyncOperation = www.SendWebRequest();
            while (!asyncOperation.isDone)
                await Task.Yield();
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("Download failed: " + www.error);
            }
            else
            {
                AssetBundle ab = AssetBundle.LoadFromMemory(www.downloadHandler.data);
                abManifestAsync = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            }
        }
    }

函数: 加载远程bundle

 /// <summary>
    /// 加载AssetsBundle 异步
    /// </summary>
    /// <param name="abName">bundle名称</param>
    /// <returns></returns>
    private async Task<LoadedAssetBundle> LoadAssetBundleAsync(string abName)
    {
        LoadedAssetBundle lab = null;
        if (!abCacheAsync.ContainsKey(abName))
        {
            string url = $"{GetBundleRemotePath()}/{abName}";
            UnityWebRequest www = UnityWebRequest.Get(url);
            UnityWebRequestAsyncOperation asyncOperation = www.SendWebRequest();
            while (!asyncOperation.isDone)
                await Task.Yield();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("Download failed: " + www.error);
            }
            else
            {
                AssetBundle ab = AssetBundle.LoadFromMemory(www.downloadHandler.data);
                lab = new LoadedAssetBundle(ab);
                abCacheAsync.Add(abName, lab);
            }

        }
        else
        {
            lab = abCacheAsync[abName];
        }
        lab.AddReferenced();
        return lab;

    }

函数:加载依赖项

   /// <summary>
    /// 加载依赖项 异步
    /// </summary>
    /// <param name="abName"></param>
    /// <returns></returns>
    private async Task<List<string>> LoadAssetBundleDependAsync(string abName)
    {

        await LoadManifestAsync();

        List<string> dependNames = new List<string>();

        string[] dependences = abManifestAsync.GetAllDependencies(abName);
        if (dependences.Length > 0)
        {
            foreach (var item in dependences)
            {
                LoadedAssetBundle lab = await LoadAssetBundleAsync(item);
                dependNames.Add(lab.GetName());
            }
        }

        return dependNames;
    }

公开函数:实例化Prefab

 /// <summary>
    /// 加载prefab 并实例化它  异步
    /// </summary>
    /// <param name="assetbundleName">AssetBundle名称</param>
    /// <param name="assetName">资源名称</param>
    /// <returns></returns>
    public async Task<GameObject> InstantiatePrefabAsync(string assetbundleName, string assetName)
    {
        assetbundleName = assetbundleName.ToLower();
        assetName = assetName.ToLower();

        LoadedAssetBundle lab = await LoadAssetBundleAsync(assetbundleName);
        List<string> dependNames = await LoadAssetBundleDependAsync(assetbundleName);


        GameObject prefab = lab.GetAsset<GameObject>(assetName);
        GameObject go = GameObject.Instantiate(prefab);

        AssetWatcher watcher = go.AddComponent<AssetWatcher>();

        watcher.Add(lab.GetName());
        watcher.Add(dependNames);

        return go;

    }

公开函数:加载资源

 /// <summary>
    /// 加载资源 异步
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="assetbundleName">AssetBundle名称</param>
    /// <param name="assetName">资源名称</param>
    /// <returns></returns>
    public async Task<T> LoadAssetAsync<T>(string assetbundleName, string assetName, GameObject watcherGo) where T : Object
    {
        if (watcherGo == null)
        {
            Debug.LogError("加载资源必须绑定GameObject,用于检测卸载资源");
            return null;
        }


        assetbundleName = assetbundleName.ToLower();
        assetName = assetName.ToLower();

        AssetWatcher watcher = watcherGo.GetComponent<AssetWatcher>();
        if (watcher == null)
        {
            watcher = watcherGo.AddComponent<AssetWatcher>();
        }


        LoadedAssetBundle lab = await LoadAssetBundleAsync(assetbundleName);
        List<string> dependNames = await LoadAssetBundleDependAsync(assetbundleName);

        watcher.Add(lab.GetName());
        watcher.Add(dependNames);


        T t = lab.GetAsset<T>(assetName);
        return t;

    }

公开函数:卸载资源

  /// <summary>
    /// 卸载bundle
    /// </summary>
    public void UnloadAssetBundle(string abName)
    {
       
        if (abCacheAsync.TryGetValue(abName, out LoadedAssetBundle lab2))
        {
            lab2.RemReferenced();
            if (!lab2.CheckHaveReferenced())
            {
                lab2.Unload();
                abCacheAsync.Remove(abName);
            }
        }
    }

OK 至此使用远程资源的功能就完成了,下面使用测试脚本测试下吧

using UnityEngine;

public class Test : MonoBehaviour
{
    private async void OnGUI()
    {
        if (GUILayout.Button("LoadCube Async"))
        {
            LoadCube();
        }

        if (GUILayout.Button("LoadSphere  Async"))
        {
            LoadSphere();
        }

        if (GUILayout.Button("LoadCapsule  Async"))
        {
            LoadCapsule();
        }
    }

    async void LoadCube()
    {
        await ResourcesManager.Instance.InstantiatePrefabAsync("prefab/cube", "cube");
    }
    async void LoadSphere()
    {
        await ResourcesManager.Instance.InstantiatePrefabAsync("prefab/Sphere", "Sphere");
    }
    async void LoadCapsule()
    {
        GameObject Capsule = await ResourcesManager.Instance.InstantiatePrefabAsync("prefab/Capsule", "Capsule");
        Material mat = await ResourcesManager.Instance.LoadAssetAsync<Material>("material/SphereMaterial2", "SphereMaterial2", Capsule);
        Capsule.GetComponent<MeshRenderer>().material = mat;
    }
}

代码直接拿去会有报错,请配合上篇文章的代码看

第1章 Unity AssetBundle 资源管理(1)--- 基础功能,包含标记、打包、加载、依赖和卸载-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_37302769/article/details/134559730

demo包:https://download.csdn.net/download/qq_37302769/88573569icon-default.png?t=N7T8https://download.csdn.net/download/qq_37302769/88573569

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值