Unity5 AssetBundle管理

//********************************************************************
// 文件名: ABMgr.cs
// 描述: AssetBundle管理
// 作者: 李偉
// 創建時間: 2015-07-16
//
//********************************************************************

using SK;
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.Collections.Generic;

public class ABMgr : Singleton<ABMgr>
{
    public void Init()
    {
        D.Log("ABMgr Init()");

        _downloadFaildNeedRemoveList = new List<string>();
        _downloadSuccessdNeedRemoveList = new List<string>();

        _assetBundleDic = new Dictionary<string, LoadedAssetBundle>();
        _downloadingWWWDic = new Dictionary<string, WWWLoad>();
        _downloadingEventDic = new Dictionary<string, DownloadingSameObjEvent>();

    }

    public void Reset()
    {
        FreeAllAssets();

        Init();
    }

/*==================================================================================*/
    private Dictionary<string, DownloadingSameObjEvent> _downloadingEventDic;
    private Dictionary<string, LoadedAssetBundle> _assetBundleDic;
    private Dictionary<string, WWWLoad> _downloadingWWWDic;
    private List<string> _downloadFaildNeedRemoveList;
    private List<string> _downloadSuccessdNeedRemoveList;




    public struct WWWLoad
    {
        private string _abName;
        private WWW _www;
        private bool _canUseCache;


        public WWW WWW
        {
            get 
            {
                return _www;
            }
        }

        public string ABName
        {
            get
            {
                return _abName;
            }
        }


        public AssetBundle AssetBundle
        {
            get
            {
                if(WWW.isDone)
                {
                    return WWW.assetBundle;
                }
                else
                {
                    D.Log("[WWWLoad] [AssetBundle] WWW is null");

                    return null;
                }
            }
        }


        public void SetData(
            bool canUseCache, 
            string url, 
            string abName,
            int version)
        {
            init();

            _canUseCache = canUseCache;
            _abName = abName;

            _www = getWWW(url, version);
        }


        private WWW getWWW(string url, int version)
        {
            if (_canUseCache)
            {
                return WWW.LoadFromCacheOrDownload(url, version);
            }
            else
            {
                return new WWW(url);
            }
        }


        private void init()
        {
            _www = null;
            _canUseCache = false;
        }


        public float GetProgress()
        {
            return _www == null ? 0f : _www.progress;
        }
    }

    public void DownloadManifest(string abName, UnityAction<string> callback)
    {
        var url = string.Format("{0}{1}{2}", PathMgr.Self.ABDownloadPath, abName, "");
        var version = Global.Self.AssetBundleVersion;

        WWWLoad load = new WWWLoad();
        load.SetData(false, url, abName,version);

        request(load, abName, callback);
    }


    public void Download(string abName, UnityAction<string> callback)
    {
        var url = string.Format("{0}{1}{2}", PathMgr.Self.ABDownloadPath, abName, "");
        var version = Global.Self.AssetBundleVersion;

        WWWLoad load = new WWWLoad();
        load.SetData(false, url, abName, version);

        request(load, abName, callback);
    }


    public void Download(string[] abNameArr, UnityAction<bool> callback)
    {
        List<string> abNameList = new List<string>();

        foreach(var item in abNameArr)
        {
            abNameList.Add(item);
        }

        Download(abNameList, callback);
    }


    public void Download(List<string> abNameList, UnityAction<bool> callback)
    {
        var successList = new List<string>();

        //定義一個action用來回調
        UnityAction<string> action = (abNameTemp) => 
        {
            if (_assetBundleDic.ContainsKey(abNameTemp) && !successList.Contains(abNameTemp))
            {
                successList.Add(abNameTemp);

                if (successList.Count == abNameList.Count && callback != null)
                {
                    callback(true);
                }
            }
        };


        foreach (var abName in abNameList)
        {
            //如果已經下載,直接加入下載成功,不需要再下載
            if (_assetBundleDic.ContainsKey(abName) && !successList.Contains(abName))
            {
                action(abName);

                continue;
            }


            var url = string.Format("{0}{1}{2}", PathMgr.Self.ABDownloadPath, abName, "");
            var version = Global.Self.AssetBundleVersion;

            WWWLoad load = new WWWLoad();
            load.SetData(false, url, abName, version);

            request(load, abName, action);
        }
    }


    private void request(WWWLoad load, string abName, UnityAction<string> downloadingSameObjAction)
    {
        if(_assetBundleDic.ContainsKey(abName))
        {
            D.Log(abName + " has downloaded.");

            return;
        }

        if (!_downloadingEventDic.ContainsKey(abName))
        {
            var evnet = new DownloadingSameObjEvent();

            _downloadingEventDic.Add(abName, evnet);
        }

        _downloadingEventDic[abName].AddListener(downloadingSameObjAction);

        if (_downloadingWWWDic.ContainsKey(abName))
        {
            D.Log(abName + " is downloading.");

            return;
        }

        _downloadingWWWDic.Add(abName, load);
    }


    public bool IsContainItem(string item)
    {
        return _assetBundleDic.ContainsKey(item);
    }


    public AssetBundle GetItem(string item)
    {
        if (IsContainItem(item))
        { 
            return _assetBundleDic[item].AssetBundle;
        }

        return null;
    }


    public Object GetItemChild(string item, string name)
    {
        return _assetBundleDic[item].AssetBundle.LoadAsset(name);
    }



    public void FreeAssets(string[] items)
    {
        foreach (var item in items)
        {
            FreeAsset(item);
        }
    }


    public void FreeAssets(List<string> items)
    {
        FreeAssets(items.ToArray());
    }


    public void FreeAllAssets()
    {
        List<string> items = new List<string>();
        foreach (KeyValuePair<string, LoadedAssetBundle> obj in _assetBundleDic)
        {
            items.Add(obj.Key);
        }

        foreach(var item in items)
        {
            FreeAsset(item);
        }
    }


    public void FreeAsset(string item)
    {
        _assetBundleDic[item].AssetBundle.Unload(false);
        _assetBundleDic.Remove(item);

        D.Log("[Asset Bundle]Free asset : " + item);
    }

    public void Update()
    {
        _downloadFaildNeedRemoveList.Clear();
        _downloadSuccessdNeedRemoveList.Clear();

        foreach (var keyValue in _downloadingWWWDic)
        {
            WWWLoad wwwLoad = keyValue.Value;

            if (wwwLoad.WWW.error != null)
            {
                D.Error(wwwLoad.WWW.error);

                _downloadFaildNeedRemoveList.Add(keyValue.Key);

                continue;
            }

            if (wwwLoad.WWW.isDone)
            {
                D.Log("[ABMgr][Downloaded] : " + keyValue.Key + " isDone");

                var loadedAssetBundle = new LoadedAssetBundle(keyValue.Key, wwwLoad.AssetBundle);

                if (!_assetBundleDic.ContainsKey(keyValue.Key))
                {
                    _assetBundleDic.Add(keyValue.Key, loadedAssetBundle);
                }

                _downloadSuccessdNeedRemoveList.Add(keyValue.Key);
            }
        }

        DownloadSuccessFaild();

        DownloadSuccess();
    }


    private void DownloadSuccessFaild()
    {
        foreach (var key in _downloadFaildNeedRemoveList)
        {
            WWWLoad wwwload = _downloadingWWWDic[key];

            _downloadingWWWDic.Remove(key);

            wwwload.WWW.Dispose();
        }
    }



    private void DownloadSuccess()
    {
        foreach (var key in _downloadSuccessdNeedRemoveList)
        {
            WWWLoad wwwload = _downloadingWWWDic[key];

            if (_downloadingEventDic.ContainsKey(key))
            {
                _downloadingEventDic[key].Invoke(key);

                _downloadingEventDic[key].RemoveAllListeners();

                _downloadingEventDic.Remove(key);
            }

            _downloadingWWWDic.Remove(key);

            wwwload.WWW.Dispose();


        }
    }
}

public class LoadedAssetBundle
{
    public string _name;
    public AssetBundle _assetBundle;
    public int _referencedCount;

    public string Name { get { return _name; } }
    public AssetBundle AssetBundle { get { return _assetBundle; } }
    public int ReferencedCount { get { return _referencedCount; } }

    public LoadedAssetBundle(string name, AssetBundle assetBundle)
    {
        _name = name;
        _assetBundle = assetBundle;
        _referencedCount = 1;
    }
}
//********************************************************************
// 文件名: Load.cs
// 描述: Load加載策略的基類
// 作者: 李偉
// 創建時間: 2015-07-16
//
//********************************************************************



using SK;
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.Collections.Generic;

public class Load
{
    private string _abName;
    private UnityAction _loadAction;
    private static AssetBundleManifest _assetBundlesManifest;

    public static void LoadAssetBundlesManifest(UnityAction callback)
    {
        if (ABMgr.Self.IsContainItem("AssetBundles"))
        {
            if (callback != null)
            {
                callback();
            }

            return;
        }

        ABMgr.Self.DownloadManifest("AssetBundles", abName =>
        {
            if ("AssetBundles" == abName && ABMgr.Self.IsContainItem("AssetBundles"))
            {
                _assetBundlesManifest = ABMgr.Self.GetItemChild("AssetBundles", "AssetBundleManifest") as AssetBundleManifest;

                if (callback != null) callback();
            }
            else
            {
                D.Error("[Load][LoadAssetBundlesManifest] ERROR");
            }
        });
    }


    public Load(string abName, UnityAction callback)
    {
        _abName = abName;
        _loadAction = callback;
    }

    public void BeginLoad()
    {
        if (ABMgr.Self.IsContainItem(_abName))
        {
            _loadAction();

            return;
        }

        if (_assetBundlesManifest != null)
        {
            string[] arr = _assetBundlesManifest.GetAllDependencies(_abName);

            if (arr.Length == 0)
            {
                ABMgr.Self.Download(_abName, abName => 
                {
                    if (abName == _abName) _loadAction();
                });
            }
            else
            {
                var needDownLoadList = new List<string>();

                foreach (var item in arr)
                {
                    if (!ABMgr.Self.IsContainItem(item)) needDownLoadList.Add(item);
                }

                ABMgr.Self.Download(needDownLoadList, isSuccess =>
                {
                    if (isSuccess)
                    {
                        ABMgr.Self.Download(_abName, abName =>
                        {
                            if (abName == _abName) _loadAction();
                        });
                    }
                });
            }
        }
    }
}
//********************************************************************
// 文件名: Singleton.cs
// 描述: 通用類
// 作者: 李偉
// 創建時間: 2015-07-15
//
//********************************************************************

using System;
using UnityEngine;
using System.Collections;
using System.Linq.Expressions;

namespace SK
{
    public class Singleton<T>  where T : new()
    {
        private static T _self;
        private static readonly object _lockObj;

        static Singleton()
        {
            _lockObj = new object();
        }

        public static T Self
        {
            get
            {
                if (_self == null)
                {
                    lock (_lockObj)
                    {
                        if (_self == null)
                        {
                            _self = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
                        }
                    }
                }

                return _self;
            }
        }
    }


    public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour 
    {
        private static T _self;
        private static readonly object _lockObj;

        static SingletonMono()
        {
            _lockObj = new object();
        }

        public static T Self
        {
            get
            {
                if (_self == null)
                {
                    lock (_lockObj)
                    {
                        if (_self == null)
                        {
                            var go = new GameObject(typeof(T).ToString()) ;
                            _self = go.AddComponent<T>();

                            DontDestroyOnLoad(go);
                        }
                    }
                }

                return _self;
            }
        }
    }
}
//********************************************************************
// 文件名: ABMgrTest.cs
// 描述: 
// 作者: 李偉
// 創建時間: 2015-07-15
//
//********************************************************************


using SK;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ABMgrTest : MonoBehaviour
{
    void Start()
    {
        Load.LoadAssetBundlesManifest(LoadAssetBundlesManifestCallback);
    }


    void LoadAssetBundlesManifestCallback()
    {
        Load logoLoad = new Load("data", logoLoadCallback);
        logoLoad.BeginLoad();


        Load boxLoad = new Load("box", boxCallback);
        boxLoad.BeginLoad();
    }


    void logoLoadCallback()
    {
        if (!ABMgr.Self.IsContainItem("data")) return;

        GameObject obj = ABMgr.Self.GetItemChild("data", "pre_cryWolfLogo") as GameObject;
        Instantiate(obj);

        GameObject obj2 = ABMgr.Self.GetItemChild("data", "pre_cryWolfLogo_url") as GameObject;
        Instantiate(obj2);
    }

    void boxCallback()
    {
        if (!ABMgr.Self.IsContainItem("box")) return;

        GameObject obj = ABMgr.Self.GetItemChild("box", "box") as GameObject;
        Instantiate(obj);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章