zoukankan      html  css  js  c++  java
  • Unity5.x版本AssetBundle加载研究

    之前说了 “Unity5.x版本AssetBundle打包研究”,没看过的请先看一下:http://www.shihuanjue.com/?p=57
    再来看本文,有一定的连接性。

    先梳理一下思路:
    要加载一个资源A,必须先去加载它的所有依赖资源
    要知道这个资源A依赖了哪些资源,必须先去加载AssetBundleManifest
    通过AssetBundleManifest对象的GetAllDependencies(A)方法,获取它依赖的所有资源。
    依赖资源都加载了,就可以去真正加载资源A了。

    注意点:
    1.资源A加载完了后,要记得Unload(false),资源A的依赖资源要在 资源A加载完成后,才能Unload(false),否则无法正常加载资源A
    2.不Unload的话也可以,那就自己做一个字典记录所有加载过的AssetBundle,还有它们的引用计数器。那样就可以先判断是否存在,然后再确定是否要去加载。

    我下面的例子,采用1的方式。就是加载完了后就Unload的方式。
    上代码

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using System;
     
    public class AssetBundleLoaderMgr : Singleton<AssetBundleLoaderMgr>
    {
        public string m_assetPath = Application.streamingAssetsPath;
        string assetTail = ".unity3d";
     
        #region LoadAssetBundle
     
        /// <summary>
        /// 加载目标资源
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public void LoadAssetBundle(string name, Action<UnityEngine.Object> callback)
        {
            name = name + assetTail;//eg:ui/panel.unity3d
     
            Action<List<AssetBundle>> action = (depenceAssetBundles) =>
            {
     
                string realName = this.GetRuntimePlatform() + "/" + name;//eg:Windows/ui/panel.unity3d
     
                LoadResReturnWWW(realName, (www) =>
                {
                    int index = realName.LastIndexOf("/");
                    string assetName = realName.Substring(index + 1);
                    assetName = assetName.Replace(assetTail, "");
                    AssetBundle assetBundle = www.assetBundle;
                    UnityEngine.Object obj = assetBundle.LoadAsset(assetName);//LoadAsset(name),这个name没有后缀,eg:panel
     
                    //卸载资源内存
                    assetBundle.Unload(false);
                    for (int i = 0; i < depenceAssetBundles.Count; i++)
                    {
                        depenceAssetBundles[i].Unload(false);
                    }
     
                    //加载目标资源完成的回调
                    callback(obj);
                });
     
            };
     
            LoadDependenceAssets(name, action);
        }
     
        /// <summary>
        /// 加载目标资源的依赖资源
        /// </summary>
        /// <param name="targetAssetName"></param>
        /// <param name="action"></param>
        private void LoadDependenceAssets(string targetAssetName, Action<List<AssetBundle>> action)
        {
            Debug.Log("要加载的目标资源:" + targetAssetName);//ui/panel.unity3d
            Action<AssetBundleManifest> dependenceAction = (manifest) =>
            {
                List<AssetBundle> depenceAssetBundles = new List<AssetBundle>();//用来存放加载出来的依赖资源的AssetBundle
     
                string[] dependences = manifest.GetAllDependencies(targetAssetName);
                Debug.Log("依赖文件个数:" + dependences.Length);
                int length = dependences.Length;
                int finishedCount = 0;
                if (length == 0)
                {
                    //没有依赖
                    action(depenceAssetBundles);
                }
                else
                {
                    //有依赖,加载所有依赖资源
                    for (int i = 0; i < length; i++)
                    {
                        string dependenceAssetName = dependences[i];
                        dependenceAssetName = GetRuntimePlatform() + "/" + dependenceAssetName;//eg:Windows/altas/heroiconatlas.unity3d
     
                        //加载,加到assetpool
                        LoadResReturnWWW(dependenceAssetName, (www) =>
                        {
                            int index = dependenceAssetName.LastIndexOf("/");
                            string assetName = dependenceAssetName.Substring(index + 1);
                            assetName = assetName.Replace(assetTail, "");
                            AssetBundle assetBundle = www.assetBundle;
                            UnityEngine.Object obj = assetBundle.LoadAsset(assetName);
                            //assetBundle.Unload(false);
                            depenceAssetBundles.Add(assetBundle);
     
                            finishedCount++;
     
                            if (finishedCount == length)
                            {
                                //依赖都加载完了
                                action(depenceAssetBundles);
                            }
                        });
                    }
                }
            };
            LoadAssetBundleManifest(dependenceAction);
        }
     
        /// <summary>
        /// 加载AssetBundleManifest
        /// </summary>
        /// <param name="action"></param>
        private void LoadAssetBundleManifest(Action<AssetBundleManifest> action)
        {
            string manifestName = this.GetRuntimePlatform();
            manifestName = manifestName + "/" + manifestName;//eg:Windows/Windows
            LoadResReturnWWW(manifestName, (www) =>
            {
                AssetBundle assetBundle = www.assetBundle;
                UnityEngine.Object obj = assetBundle.LoadAsset("AssetBundleManifest");
                assetBundle.Unload(false);
                AssetBundleManifest manif = obj as AssetBundleManifest;
                action(manif);
            });
        }
        #endregion
     
        #region ExcuteLoader
        public void LoadResReturnWWW(string name, Action<WWW> callback)
        {
            string path = "file://" + this.m_assetPath + "/" + name;
            Debug.Log("加载:" + path);
            StartCoroutine(LoaderRes(path, callback));
        }
     
        IEnumerator LoaderRes(string path, Action<WWW> callback)
        {
            WWW www = new WWW(path);
            yield return www;
            if (www.isDone)
            {
                callback(www);
            }
        }
        #endregion
     
        #region Util
        /// <summary>
        /// 平台对应文件夹
        /// </summary>
        /// <returns></returns>
        private string GetRuntimePlatform()
        {
            string platform = "";
            if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor)
            {
                platform = "Windows";
            }
            else if (Application.platform == RuntimePlatform.Android)
            {
                platform = "Android";
            }
            else if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                platform = "IOS";
            }
            else if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor)
            {
                platform = "OSX";
            }
            return platform;
        }
    }
    #endregion

    测试一下咯

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
     
    public class TestAssetBundleLoader : MonoBehaviour
    {
        Dictionary<string, GameObject> GameObjectPool = new Dictionary<string, GameObject>();
     
        void Start()
        {
            //要加载的资源的队列
            Queue<string> needLoadQueue = new Queue<string>();
            needLoadQueue.Enqueue("ui/plane");
            needLoadQueue.Enqueue("ui/cube");
            needLoadQueue.Enqueue("ui/sphere");
     
            Load(needLoadQueue);
        }
     
        void Load(Queue<string> needLoadQueue)
        {
            if (needLoadQueue.Count > 0)
            {
                string needLoadAssetName = needLoadQueue.Dequeue();
                AssetBundleLoaderMgr.Instance.LoadAssetBundle(needLoadAssetName, (obj) =>
                {
                    GameObject go = GameObject.Instantiate(obj) as GameObject;
                    int index = needLoadAssetName.LastIndexOf("/");
                    string assetName = needLoadAssetName.Substring(index + 1);
     
                    //加载出来的GameObject放到GameObjectPool存储
                    GameObjectPool.Add(assetName, go);
     
                    Load(needLoadQueue);
                });
            }
            else
            {
                Debug.Log("all finished");
            }
        }
    }

    有图有真相

    可能代码写的还有很多优化的地方 ,毕竟100个人有100种写法,思路才是最重要的。你说呢?
    其实我想说的是,代码都在了,自己尝试一下吧!

  • 相关阅读:
    axios的封装
    单行和多行文本溢出省略号显示!!!
    vue2源码-响应式处理(学习笔记)-2
    vue2源码-rollup的配置(学习笔记)-1
    js的垃圾回收机制
    立即执行函数
    闭包笔记
    vue3.0的CompositionAPI
    Create gym environment with your own xml file and training it using her of baseline
    Brief introduction to mujoco or gym modeling using xml
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5488778.html
Copyright © 2011-2022 走看看