1. 程式人生 > >Unity3D遊戲開發框架-資源管理類ResourceManage

Unity3D遊戲開發框架-資源管理類ResourceManage

using UnityEngine;
using System.Collections;

/// <summary>
/// 資源載入回撥
/// </summary>
public interface IResLoadListener  
{
    void Finish(object asset);

    void Failure();
}
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 資源資訊
///
</summary>
public class AssetInfo { /// <summary> /// 資源 /// </summary> public object asset; /// <summary> /// 是否常駐記憶體 /// </summary> public bool isKeepInMemory; /// <summary> /// 資源堆疊數量 /// </summary> public int stackCount = 0; } /// <summary>
/// 資源載入資訊 /// </summary> public class RequestInfo { /// <summary> /// 資源反饋資訊 /// </summary> public ResourceRequest request; /// <summary> /// 是否常駐記憶體 /// </summary> public bool isKeepInMemory; /// <summary> /// 載入完成之後的回撥 /// </summary> public List<IResLoadListener> linsteners; public
void AddListener(IResLoadListener listener) { if (linsteners == null) { linsteners = new List<IResLoadListener>() { listener }; } else { if (!linsteners.Contains(listener)) { linsteners.Add(listener); } } } /// <summary> /// 資源名稱 /// </summary> public string assetName; public string assetFullName { get { return ResMgr.Instance.GetFileFullName(assetName); } } /// <summary> /// 資源型別 /// </summary> public Type type; /// <summary> /// 資源是否載入完成 /// </summary> public bool IsDone { get { return (request != null && request.isDone); } } /// <summary> /// 載入到的資源 /// </summary> public object Asset { get { return request != null ? request.asset : null; } } public void LoadAsync() { request = Resources.LoadAsync(assetFullName, type); } }
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;

public class ResMgr : EventNode,IEventListener 
{
    private Dictionary<string, string> mAssetPathDic = new Dictionary<string, string>();
    public string GetFileFullName(string assetName)
    {
        if (mAssetPathDic.Count == 0)
        {
            UnityEngine.TextAsset tex = Resources.Load<TextAsset>("res");
            StringReader sr = new StringReader(tex.text);
            string fileName = sr.ReadLine();
            while (fileName != null)
            {
                Debug.Log("fileName =" + fileName);
                string [] ss = fileName.Split('=');
                mAssetPathDic.Add(ss[0], ss[1]);
                fileName = sr.ReadLine();
            }
        }
        return assetName = mAssetPathDic[assetName] + "/" + assetName; 
    }
    /// <summary>
    /// 所有資源字典
    /// </summary>
    private Dictionary<string, AssetInfo> mDicAaaet = new Dictionary<string, AssetInfo>();

    /// <summary>
    /// CPU 個數
    /// </summary>
    private int mProcessorCount = 0;

    private static ResMgr mInstance;
    public static ResMgr Instance
    {
        get
        {
            return mInstance;
        }
    }



    // Awake is called when the script instance is being loaded.
    void Awake()
    {
        mInstance = this;
        DontDestroyOnLoad(this.gameObject);
        AttachEventListener(EventDef.ResLoadFinish, this);
        mProcessorCount = SystemInfo.processorCount > 0 && SystemInfo.processorCount <= 8 ? SystemInfo.processorCount : 1;
    }

    void OnDestroy()
    {
        if (Instance != null)
        {
            Instance.DetachEventListener(EventDef.ResLoadFinish, this);
        }
    }

    /// <summary>
    /// 正在載入的列表
    /// </summary>
    public List<RequestInfo> mInLoads = new List<RequestInfo>();

    /// <summary>
    /// 等待載入的列表
    /// </summary>
    public Queue<RequestInfo> mWaitting = new Queue<RequestInfo>();

    /// <summary>
    /// 資源載入堆疊
    /// </summary>
    public Stack<List<string>> mAssetStack = new Stack<List<string>>();

    #region 載入資源
    public void Load(string assetName, IResLoadListener listener, Type type = null, bool isKeepInMemory = false, bool isAsync = true)
    {
        if (mDicAaaet.ContainsKey(assetName))
        {
            listener.Finish(mDicAaaet[assetName]);
            return;
        }
        if (isAsync)
        {
            LoadAsync(assetName, listener,isKeepInMemory,type);
        }
    }
    #endregion

    #region 非同步Res載入
    private void LoadAsync(string assetName, IResLoadListener listener,bool isKeepInMemory,Type type)
    {
        for (int i = 0; i < mInLoads.Count; i++)
        {
            if (mInLoads[i].assetName == assetName)
            {
                mInLoads[i].AddListener(listener);
                return;
            }
        }

        foreach(RequestInfo info in mWaitting)
        {
            if (info.assetName == assetName)
            {
                info.AddListener(listener);
                return;
            }
        }

        RequestInfo requestInfo = new RequestInfo();
        requestInfo.assetName = assetName;
        requestInfo.AddListener(listener);
        requestInfo.isKeepInMemory = isKeepInMemory;
        requestInfo.type = type == null ? typeof(GameObject) : type;
        mWaitting.Enqueue(requestInfo);
    }
 #endregion

    #region 資源處理

        /// <summary>
        /// 從資源字典中取得一個資源
        /// </summary>
        /// <param name="assetName">資源名稱</param>
        /// <returns></returns>
        public AssetInfo GetAsset(string assetName)
        {
            AssetInfo info = null;
            mDicAaaet.TryGetValue(assetName,out info);
            return info;
        }

        /// <summary>
        /// 釋放一個資源
        /// </summary>
        /// <param name="assetName">資源名稱</param>
        public void ReleaseAsset(string assetName)
        {
            AssetInfo info = null;
            mDicAaaet.TryGetValue(assetName, out info);

            if (info != null && !info.isKeepInMemory)
            {
                mDicAaaet.Remove(assetName);
            }
        }

        /// <summary>
        /// 修改資源是否常駐記憶體
        /// </summary>
        /// <param name="assetName">資源名稱</param>
        /// <param name="IsKeepInMemory">是否常駐記憶體</param>
        public void IsKeepInMemory(string assetName,bool IsKeepInMemory)
        {
            AssetInfo info = null;
            mDicAaaet.TryGetValue(assetName, out info);

            if (info != null)
            {
                info.isKeepInMemory = IsKeepInMemory;
            }
        }
    #endregion

    #region 資源釋放以及監聽

        /// <summary>
        /// 把資源壓入頂層棧內
        /// </summary>
        /// <param name="assetName">資源名稱</param>
        public void AddAssetToName(string assetName)
        {
            if (mAssetStack.Count == 0)
            {
                mAssetStack.Push(new List<string>() { assetName });
            }

            List <string> list = mAssetStack.Peek();
            list.Add(assetName);
        }

        /// <summary>
        /// 開始讓資源入棧
        /// </summary>
        public void PushAssetStack()
        {
            List<string> list = new List<string>();
            foreach(KeyValuePair<string,AssetInfo> info in mDicAaaet)
            {
                info.Value.stackCount++;
                list.Add(info.Key);
            }

            mAssetStack.Push(list);
        }

        /// <summary>
        /// 釋放棧內資源
        /// </summary>
        public void PopAssetStack()
        {
            if (mAssetStack.Count == 0) return;

            List<string> list = mAssetStack.Pop();
            List<string> removeList = new List<string>();
            AssetInfo info = null;
            for (int i = 0; i < list.Count;i++ )
            {
                if (mDicAaaet.TryGetValue(list[i],out info))
                {
                    info.stackCount--;
                    if (info.stackCount < 1 && !info.isKeepInMemory)
                    {
                        removeList.Add(list[i]);
                    }
                }
            }
            for (int i = 0; i < removeList.Count;i++ )
            {
                if (mDicAaaet.ContainsKey(removeList[i]))
                mDicAaaet.Remove(removeList[i]);
            }

            GC();
        }

        /// <summary>
        /// 釋放
        /// </summary>
        public void GC()
        {
            Resources.UnloadUnusedAssets();
            System.GC.Collect();
        }


    #endregion

    void Update()
    {
        if (mInLoads.Count > 0)
        {
            for (int i = mInLoads.Count - 1; i >= 0; i--)
            {
                if (mInLoads[i].IsDone)
                {
                    RequestInfo info = mInLoads[i];
                    SendEvent(EventDef.ResLoadFinish, info);
                    mInLoads.RemoveAt(i);
                }
            }
        }

        while (mInLoads.Count < mProcessorCount && mWaitting.Count > 0)
        {
            RequestInfo info = mWaitting.Dequeue();
            mInLoads.Add(info);
            info.LoadAsync();
        }
    }



    public bool HandleEvent(int id, object param1, object param2)
    {
        switch (id)
        {
            case EventDef.ResLoadFinish:
                RequestInfo info = param1 as RequestInfo;
                if (info != null)
                {
                    if (info.Asset != null)
                    {
                        AssetInfo asset = new AssetInfo();
                        asset.isKeepInMemory = info.isKeepInMemory;
                        asset.asset = info.Asset;
                        if (!mDicAaaet.ContainsKey(info.assetName))
                        {
                            mDicAaaet.Add(info.assetName, asset);
                        }

                        for (int i = 0; i < info.linsteners.Count;i++ )
                        {
                            if (info.linsteners[i] != null)
                            {
                                info.linsteners[i].Finish(info.Asset);
                            }
                        }
                        AddAssetToName(info.assetName);
                    }
                }
                else
                {
                    for (int i = 0; i < info.linsteners.Count; i++)
                    {
                        if (info.linsteners[i] != null)
                        {
                            info.linsteners[i].Failure();
                        }
                    }
                }
                return false;
        }
        return false;
    }

    public int EventPriority()
    {
        return 0;
    }
}