Пример #1
0
        //根据文件Crc加载一个ResourcesItem出来 也会加载这个文件的所有依赖Item
        public MResourceItem LoadResourcesAssetBundle(uint crc)
        {
            MResourceItem mResourceItem = null;

            if (!m_resourcesItemDic.TryGetValue(crc, out mResourceItem) || mResourceItem == null)
            {
                MDebug.singleton.AddErrorLog("没有找到Crc " + crc.ToString());
                return(mResourceItem);
            }

            if (mResourceItem.m_assetBundle == null)
            {
                mResourceItem.m_assetBundle = LoadAssetBundle(mResourceItem.m_abName);
                if (mResourceItem.m_abDependence != null)
                {
                    for (int i = 0; i < mResourceItem.m_abDependence.Count; i++)
                    {
                        //Dependence存储的是依赖的ABName
                        LoadAssetBundle(mResourceItem.m_abDependence[i]);
                    }
                }
                return(mResourceItem);
            }
            return(mResourceItem);
        }
Пример #2
0
        /// <summary>
        /// 对已经加载过的资源 做资源缓存
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mResourceItem"></param>
        /// <param name="crc"></param>
        /// <param name="obj"></param>
        /// <param name="addRefCount"></param>
        protected void CacheResource(string path, ref MResourceItem mResourceItem, uint crc, Object obj, int addRefCount = 1)
        {
            //缓存太多 清楚最早没有使用的资源
            ClearEarlierUnUsedResItem();

            if (mResourceItem == null)
            {
                MDebug.singleton.AddErrorLog(" MResourceItem == null Path : " + path);
                return;
            }

            if (obj == null)
            {
                MDebug.singleton.AddErrorLog(" Object == null Path : " + path);
                return;
            }

            mResourceItem.m_object      = obj;
            mResourceItem.m_guid        = obj.GetInstanceID();
            mResourceItem.m_lastUseTime = Time.realtimeSinceStartup;
            mResourceItem.RefCount      = addRefCount;

            MResourceItem oldResourceItem = null;

            if (m_resourcesItemDic.TryGetValue(crc, out oldResourceItem))
            {
                m_resourcesItemDic[mResourceItem.m_crc] = mResourceItem;
            }
            else
            {
                m_resourcesItemDic.Add(mResourceItem.m_crc, mResourceItem);
            }
        }
Пример #3
0
        /// <summary>
        /// 不需要实例化的资源的卸载
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="destoryCompletly">是否彻底删除 false 则加入资源缓存列表中管理 true 彻底删除</param>
        /// <returns></returns>
        public bool ReleaseResource(Object obj, bool destoryCompletly = false)
        {
            if (obj == null)
            {
                return(false);
            }
            MResourceItem mResourceItem = null;

            foreach (var item in m_resourcesItemDic.Values)
            {
                if (item.m_guid == obj.GetInstanceID())
                {
                    mResourceItem = item;
                }
            }
            if (mResourceItem == null)
            {
                MDebug.singleton.AddErrorLog(" m_resourcesItemDic 不存在这个资源 resName : " + obj.name);
                return(false);
            }

            mResourceItem.RefCount--;
            DestoryResourceItem(mResourceItem, destoryCompletly);
            return(true);
        }
Пример #4
0
        /// <summary>
        /// 回收一个资源
        /// </summary>
        /// <param name="mResourceItem"></param>
        /// <param name="destoryCatchResItem">是否彻底删除 false 则加入资源缓存列表中管理 true 彻底删除</param>
        protected void DestoryResourceItem(MResourceItem mResourceItem, bool destoryCompletly = false)
        {
            if (mResourceItem == null || mResourceItem.RefCount > 0)
            {
                return;
            }

            //从已经加载的资源缓存里面删除
            if (!m_resourcesItemDic.Remove(mResourceItem.m_crc))
            {
                return;
            }

            //False 则加入没有引用的资源缓存列表中管理
            if (!destoryCompletly)
            {
                m_resourcesMapItemList.InsertToHead(mResourceItem);
                return;
            }

            //释放在AssetBundle里面的引用
            MAssetBundleManager.singleton.ReleaseAsset(mResourceItem);

            //清除资源对应的对象池
            MObjectManager.singleton.ClearPoolObject(mResourceItem.m_crc);

            if (mResourceItem.m_object != null)
            {
                mResourceItem.m_object = null;
#if UNITY_EDITOR
                Resources.UnloadUnusedAssets();
#endif
            }
        }
Пример #5
0
        /// <summary>
        /// 同步加载资源 针对给ObjectManager
        /// </summary>
        /// <param name="resPath">资源路径</param>
        /// <param name="mResourceObjectItem">ObjecyResItem</param>
        public MResourceObjectItem LoadToResourceObject(string resPath, MResourceObjectItem mResourceObjectItem)
        {
            if (mResourceObjectItem == null)
            {
                return(null);
            }

            uint          crc           = mResourceObjectItem.m_crc == 0 ? MCrcHelper.GetCRC32(resPath) : mResourceObjectItem.m_crc;
            MResourceItem mResourceItem = GetCacheResourceItem(crc);

            if (mResourceItem != null && mResourceItem.m_object != null)
            {
                mResourceObjectItem.m_resItem = mResourceItem;
                return(mResourceObjectItem);
            }

            Object obj = null;

#if UNITY_EDITOR
            if (!m_isLoadFormAssetBundle)
            {
                mResourceItem = MAssetBundleManager.singleton.FindResourceItem(crc);
                if (mResourceItem == null)
                {
                    mResourceItem       = new MResourceItem();
                    mResourceItem.m_crc = crc;
                }
                mResourceItem.m_path = resPath;
                if (mResourceItem.m_object != null)
                {
                    obj = mResourceItem.m_object as Object;
                }
                else
                {
                    obj = LoadAssetFormEditor <Object>(mResourceItem.m_path);
                }
            }
#endif
            if (obj == null)
            {
                mResourceItem        = MAssetBundleManager.singleton.LoadResourcesAssetBundle(crc);
                mResourceItem.m_path = resPath;
                if (mResourceItem.m_object != null)
                {
                    obj = mResourceItem.m_object as Object;
                }
                else
                {
                    obj = mResourceItem.m_assetBundle.LoadAsset <Object>(mResourceItem.m_path);
                }
            }

            CacheResource(resPath, ref mResourceItem, crc, obj);
            mResourceItem.m_clear         = mResourceObjectItem.m_isClear;
            mResourceObjectItem.m_resItem = mResourceItem;
            return(mResourceObjectItem);
        }
Пример #6
0
        /// <summary>
        /// 资源的预加载 这里和同步加载微小区别 就是不需要引用计数 设置该预先加载的资源 在卸载的时候不卸载
        /// 就是直接加载 然后卸载
        /// </summary>
        /// <param name="resPath">Res path.</param>
        public void PreLoadRes(string resPath)
        {
            if (string.IsNullOrEmpty(resPath))
            {
                return;
            }
            uint crc = MCrcHelper.GetCRC32(resPath);
            //预加载到内存中 不需要进行应用计数
            MResourceItem mResourceItem = GetCacheResourceItem(crc, 0);

            if (mResourceItem != null)
            {
                return;
            }

            Object obj = null;

#if UNITY_EDITOR
            //编辑器模式下 直接从本地拿到资源
            if (!m_isLoadFormAssetBundle)
            {
                mResourceItem = MAssetBundleManager.singleton.FindResourceItem(crc);
                if (mResourceItem.m_object != null)
                {
                    if (mResourceItem.m_object != null)
                    {
                        obj = mResourceItem.m_object;
                    }
                    else
                    {
                        obj = LoadAssetFormEditor <Object>(resPath);
                    }
                }
            }
#endif
            if (obj == null)
            {
                mResourceItem = MAssetBundleManager.singleton.LoadResourcesAssetBundle(crc);
                if (mResourceItem != null && mResourceItem.m_assetBundle != null)
                {
                    if (mResourceItem.m_object != null)
                    {
                        obj = mResourceItem.m_object;
                    }
                    else
                    {
                        obj = mResourceItem.m_assetBundle.LoadAsset <Object>(mResourceItem.m_assetName);
                    }
                }
            }

            CacheResource(resPath, ref mResourceItem, crc, obj);
            mResourceItem.m_clear = false;
            //切换场景不清空缓存
            ReleaseResource(obj, false);
        }
Пример #7
0
        //根据Crc返回ResourceItem 这里Crc是资源的全路径
        public MResourceItem FindResourceItem(uint crc)
        {
            MResourceItem mResourceItem = null;

            if (m_resourcesItemDic.TryGetValue(crc, out mResourceItem))
            {
                return(mResourceItem);
            }
            return(null);
        }
Пример #8
0
        //根据资源全路径返回ResourceItem
        public MResourceItem FindResourceItem(string assetPath)
        {
            uint          crc           = MCrcHelper.GetCRC32(assetPath);
            MResourceItem mResourceItem = null;

            if (m_resourcesItemDic.TryGetValue(crc, out mResourceItem))
            {
                return(mResourceItem);
            }
            return(null);
        }
Пример #9
0
        /// <summary>
        /// 同步资源加载 外部直接调用 仅用于加载不需要实例化的资源 例如Texture 音频等
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="resPath">资源路径</param>
        /// <returns></returns>
        public T LoadResource <T>(string resPath) where T : UnityEngine.Object
        {
            if (string.IsNullOrEmpty(resPath))
            {
                return(null);
            }
            uint          crc           = MCrcHelper.GetCRC32(resPath);
            MResourceItem mResourceItem = GetCacheResourceItem(crc);

            if (mResourceItem != null)
            {
                return(mResourceItem.m_object as T);
            }

            T obj = null;

#if UNITY_EDITOR
            //编辑器模式下 直接从本地拿到资源
            if (!m_isLoadFormAssetBundle)
            {
                mResourceItem = MAssetBundleManager.singleton.FindResourceItem(crc);
                if (mResourceItem.m_object != null)
                {
                    if (mResourceItem.m_object != null)
                    {
                        obj = mResourceItem.m_object as T;
                    }
                    else
                    {
                        obj = LoadAssetFormEditor <T>(resPath);
                    }
                }
            }
#endif
            if (obj == null)
            {
                mResourceItem = MAssetBundleManager.singleton.LoadResourcesAssetBundle(crc);
                if (mResourceItem != null && mResourceItem.m_assetBundle != null)
                {
                    if (mResourceItem.m_object != null)
                    {
                        obj = mResourceItem.m_object as T;
                    }
                    else
                    {
                        obj = mResourceItem.m_assetBundle.LoadAsset <T>(mResourceItem.m_assetName);
                    }
                }
            }

            CacheResource(resPath, ref mResourceItem, crc, obj);
            return(obj);
        }
Пример #10
0
        //从AB文件中加载AB的所有信息文件
        public bool LoadAssetBundleConfig()
        {
            if (m_resourcesItemDic == null)
            {
                m_resourcesItemDic = new Dictionary <uint, MResourceItem>();
            }

            m_resourcesItemDic.Clear();
            string      abConfigPath = MPathUtils.ASSETBUNDLE_PATH + "/" + MPathUtils.ASSETBUNDLE_AB_DATA_NAME;
            AssetBundle abData       = AssetBundle.LoadFromFile(abConfigPath);

            if (abData != null)
            {
                TextAsset textAsset = abData.LoadAsset <TextAsset>(MPathUtils.ASSETBUNDLE_AB_BYTES_NAME);
                if (textAsset)
                {
                    MemoryStream       memoryStream       = new MemoryStream(textAsset.bytes);
                    BinaryFormatter    binaryFormatter    = new BinaryFormatter();
                    MAssetBundleConfig mAssetBundleConfig = (MAssetBundleConfig)binaryFormatter.Deserialize(memoryStream);
                    memoryStream.Close();

                    for (int i = 0; i < mAssetBundleConfig.AssetBundleList.Count; i++)
                    {
                        MAssetBundleBase mAssetBundleBase = mAssetBundleConfig.AssetBundleList[i];
                        MResourceItem    mResource        = new MResourceItem();
                        mResource.m_crc          = mAssetBundleBase.Crc;
                        mResource.m_abName       = mAssetBundleBase.AbName;
                        mResource.m_assetName    = mAssetBundleBase.AssetName;
                        mResource.m_path         = mAssetBundleBase.Path;
                        mResource.m_abDependence = mAssetBundleBase.AbDependence;
                        if (m_resourcesItemDic.ContainsKey(mResource.m_crc))
                        {
                            MDebug.singleton.AddErrorLog("已经添加了这个数据信息 :AbName " + mResource.m_abName + "资源名 " + mResource.m_assetName);
                        }
                        else
                        {
                            m_resourcesItemDic.Add(mResource.m_crc, mResource);
                        }
                    }
                    return(true);
                }
                else
                {
                    MDebug.singleton.AddErrorLog("这个AB文件中找不到这个资源 ResName " + MPathUtils.ASSETBUNDLE_AB_BYTES_NAME);
                    return(false);
                }
            }
            else
            {
                MDebug.singleton.AddErrorLog("请检查AB文件找不到这个Ab Path " + abConfigPath);
                return(false);
            }
        }
Пример #11
0
        /// <summary>
        /// 提供一个操作引用计数的方法
        /// </summary>
        /// <param name="crc">crc</param>
        /// <param name="Count">计数</param>
        /// <returns></returns>
        public int DeCreaseResourceRef(uint crc, int count = 1)
        {
            MResourceItem mResourceItem = null;

            if (!m_resourcesItemDic.TryGetValue(crc, out mResourceItem) && mResourceItem != null)
            {
                return(0);
            }
            mResourceItem.RefCount -= count;

            return(mResourceItem.RefCount);
        }
Пример #12
0
        /// <summary>
        /// 提供一个操作引用计数的方法
        /// </summary>
        /// <param name="crc">crc</param>
        /// <param name="Count">计数</param>
        /// <returns></returns>
        public int InCreaseResourceRef(uint crc, int count = 1)
        {
            MResourceItem mResourceItem = null;

            if (!m_resourcesItemDic.TryGetValue(crc, out mResourceItem) && mResourceItem != null)
            {
                return(0);
            }
            mResourceItem.RefCount     += count;
            mResourceItem.m_lastUseTime = Time.realtimeSinceStartup;

            return(mResourceItem.RefCount);
        }
Пример #13
0
        protected MResourceItem GetCacheResourceItem(uint crc, int addRefCount = 1)
        {
            MResourceItem mResourceItem = null;

            if (m_resourcesItemDic.TryGetValue(crc, out mResourceItem) && mResourceItem != null)
            {
                mResourceItem.RefCount     += addRefCount;
                mResourceItem.m_lastUseTime = Time.realtimeSinceStartup;

                //容错处理 理论上不会进来这个判定
                if (mResourceItem.RefCount <= 1)
                {
                    m_resourcesMapItemList.Remove(mResourceItem);
                }
            }
            return(mResourceItem);
        }
Пример #14
0
        /// <summary>
        /// 依据文件路径 不需要实例化的资源的卸载
        /// </summary>
        /// <param name="resPath">Res path.</param>
        /// <param name="destoryCompletly">If set to <c>true</c> destory completly.</param>
        public bool ReleaseResource(string resPath, bool destoryCompletly = false)
        {
            if (string.IsNullOrEmpty(resPath))
            {
                return(false);
            }
            uint          crc           = MCrcHelper.GetCRC32(resPath);
            MResourceItem mResourceItem = null;

            if (!m_resourcesItemDic.TryGetValue(crc, out mResourceItem) && mResourceItem != null)
            {
                MDebug.singleton.AddErrorLog(" m_resourcesItemDic 不存在这个资源 resPath : " + resPath);
                return(false);
            }
            mResourceItem.RefCount--;
            DestoryResourceItem(mResourceItem, destoryCompletly);
            return(true);
        }
Пример #15
0
        //根据ResourceItem 做资源的释放
        public void ReleaseAsset(MResourceItem mResourceItem)
        {
            if (mResourceItem == null)
            {
                return;
            }

            if (mResourceItem.m_abDependence != null && mResourceItem.m_abDependence.Count > 0)
            {
                for (int i = 0; i < mResourceItem.m_abDependence.Count; i++)
                {
                    //卸载依赖项
                    UnLoadAssetBundle(mResourceItem.m_abDependence[i]);
                }
            }
            //卸载自己
            UnLoadAssetBundle(mResourceItem.m_abName);
        }
Пример #16
0
        /// <summary>
        /// 给ObjectManager的释放对象的接口 依据MResourceObjectItem对对象做释放
        /// </summary>
        /// <param name="mResourceObjectItem">ObjectManager 对象</param>
        /// <param name="destoryCompletly">是否彻底删除</param>
        public bool ReleaseResource(MResourceObjectItem mResourceObjectItem, bool destoryCompletly = false)
        {
            if (mResourceObjectItem == null || mResourceObjectItem.m_resItem == null || mResourceObjectItem.m_resItem.m_object == null)
            {
                return(false);
            }

            MResourceItem mResourceItem = null;

            if (!m_resourcesItemDic.TryGetValue(mResourceObjectItem.m_crc, out mResourceItem) && mResourceItem != null)
            {
                MDebug.singleton.AddErrorLog(" m_resourcesItemDic 不存在这个资源 resPath : " + mResourceItem.m_path);
                return(false);
            }
            Object.Destroy(mResourceObjectItem.m_cloneObeject);
            mResourceItem.RefCount--;
            DestoryResourceItem(mResourceItem, destoryCompletly);
            return(true);
        }
Пример #17
0
        /// <summary>
        /// 异步加载资源 仅加载不需要实例化的资源 音频 图片等等
        /// </summary>
        public void AsyncLoadResource(string resPath, OnAsyncLoadFinished onAsyncLoadFinished, LoadResPriority loadResPriority, object[] parms = null)
        {
            if (string.IsNullOrEmpty(resPath))
            {
                return;
            }

            uint          crc           = MCrcHelper.GetCRC32(resPath);
            MResourceItem mResourceItem = GetCacheResourceItem(crc);

            if (mResourceItem != null && mResourceItem.m_object != null)
            {
                if (onAsyncLoadFinished != null)
                {
                    onAsyncLoadFinished(resPath, mResourceItem.m_object, parms);
                }
                return;
            }

            //判断下对象是不是在加载中
            AsyncLoadResParam asyncLoadResParam = null;

            if (!m_asyncLoadingAssetDic.TryGetValue(crc, out asyncLoadResParam) || asyncLoadResParam == null)
            {
                asyncLoadResParam                   = m_asyncLoadResParamPool.Spawn(true);
                asyncLoadResParam.m_crc             = crc;
                asyncLoadResParam.m_resPath         = resPath;
                asyncLoadResParam.m_loadResPriority = loadResPriority;
                //结果保存
                m_asyncAssetLoadingList[(int)loadResPriority].Add(asyncLoadResParam);
                m_asyncLoadingAssetDic.Add(crc, asyncLoadResParam);
            }

            //添加回调
            AsyncCallBack m_asyncCallBack = m_asyncCallBackPool.Spawn(true);

            m_asyncCallBack.m_onAsyncLoadFinished = onAsyncLoadFinished;
            m_asyncCallBack.m_parms = parms;
            asyncLoadResParam.m_asyncCallBacks.Add(m_asyncCallBack);
        }
Пример #18
0
        /// <summary>
        /// 异步加载的携程
        /// </summary>
        /// <returns></returns>
        IEnumerator AsyncLoader()
        {
            List <AsyncCallBack> callBackList;
            //用于记录上次的加载时间
            long lastReturnTime = System.DateTime.Now.Ticks;

            while (true)
            {
                //标志位 用于判读在For循环中是否已经return过了
                bool isYieldReturn = false;

                for (int i = 0; i < (int)LoadResPriority.RES_LOAD_LEVEL_COUNT; i++)
                {
                    List <AsyncLoadResParam> cAsyncLoadResList = m_asyncAssetLoadingList[i];
                    if (m_asyncAssetLoadingList[i] == null)
                    {
                        continue;
                    }
                    if (cAsyncLoadResList.Count <= 0)
                    {
                        continue;
                    }

                    AsyncLoadResParam asyncLoadResParam = cAsyncLoadResList[0];
                    cAsyncLoadResList.RemoveAt(0);
                    callBackList = asyncLoadResParam.m_asyncCallBacks;

                    Object        obj           = null;
                    MResourceItem mResourceItem = null;
#if UNITY_EDITOR
                    if (!m_isLoadFormAssetBundle)
                    {
                        obj = LoadAssetFormEditor <Object>(asyncLoadResParam.m_resPath);
                        //模拟异步
                        yield return(new WaitForSeconds(0.2f));

                        mResourceItem = MAssetBundleManager.singleton.FindResourceItem(asyncLoadResParam.m_crc);
                        if (mResourceItem == null)
                        {
                            mResourceItem       = new MResourceItem();
                            mResourceItem.m_crc = asyncLoadResParam.m_crc;
                        }
                    }
#endif
                    if (obj == null)
                    {
                        mResourceItem = MAssetBundleManager.singleton.LoadResourcesAssetBundle(asyncLoadResParam.m_crc);
                        if (mResourceItem != null && mResourceItem.m_assetBundle != null)
                        {
                            AssetBundleRequest assetBundleRequest = null;
                            if (asyncLoadResParam.m_isSprite)
                            {
                                assetBundleRequest = mResourceItem.m_assetBundle.LoadAssetAsync <Sprite>(mResourceItem.m_assetName);
                            }
                            else
                            {
                                assetBundleRequest = mResourceItem.m_assetBundle.LoadAssetAsync(mResourceItem.m_assetName);
                            }
                            yield return(assetBundleRequest);

                            if (assetBundleRequest.isDone)
                            {
                                obj = assetBundleRequest.asset;
                            }
                            lastReturnTime = System.DateTime.Now.Ticks;
                        }
                    }
                    //资源缓存
                    CacheResource(asyncLoadResParam.m_resPath, ref mResourceItem, asyncLoadResParam.m_crc, obj, callBackList.Count);
                    //处理加载完成的回调
                    for (int z = 0; z < callBackList.Count; z++)
                    {
                        AsyncCallBack callBack = callBackList[z];

                        //------------------------异步加载处理需要实例化的资源----------------------------
                        if (callBack != null && callBack.m_onAsyncLoadObjectFinished != null && callBack.m_resourceObjectItem != null)
                        {
                            MResourceObjectItem mResourceObjectItem = callBack.m_resourceObjectItem;
                            callBack.m_resourceObjectItem.m_resItem = mResourceItem;
                            callBack.m_onAsyncLoadObjectFinished(asyncLoadResParam.m_resPath, callBack.m_resourceObjectItem, callBack.m_resourceObjectItem.m_parms);
                            callBack.m_onAsyncLoadObjectFinished = null;
                        }

                        //------------------------异步加载处理不需要实例化的Object资源----------------------------
                        if (callBack != null && callBack.m_onAsyncLoadFinished != null)
                        {
                            callBack.m_onAsyncLoadFinished(asyncLoadResParam.m_resPath, obj, callBack.m_parms);
                            callBack.m_onAsyncLoadFinished = null;
                        }
                        //异步加载CallBack对象回收
                        callBack.Reset();
                        m_asyncCallBackPool.Recycle(callBack);
                    }

                    obj = null;
                    callBackList.Clear();
                    //从正在异步加载的Dic里面移除
                    m_asyncLoadingAssetDic.Remove(mResourceItem.m_crc);

                    //异步加载中间对象回收
                    asyncLoadResParam.Reset();
                    m_asyncLoadResParamPool.Recycle(asyncLoadResParam);

                    //上下写了两个同样的Return逻辑 是因为如果加载比较大的资源 可能在这个For循环内就需要多帧 所以这里也做了一个判定
                    if (!isYieldReturn || System.DateTime.Now.Ticks - lastReturnTime > MAX_WAITTIME)
                    {
                        lastReturnTime = System.DateTime.Now.Ticks;
                        yield return(null);

                        isYieldReturn = true;
                    }
                }

                if (!isYieldReturn || System.DateTime.Now.Ticks - lastReturnTime > MAX_WAITTIME)
                {
                    lastReturnTime = System.DateTime.Now.Ticks;
                    yield return(null);
                }
            }
        }