//根据文件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); }
/// <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); } }
/// <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); }
/// <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 } }
/// <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); }
/// <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); }
//根据Crc返回ResourceItem 这里Crc是资源的全路径 public MResourceItem FindResourceItem(uint crc) { MResourceItem mResourceItem = null; if (m_resourcesItemDic.TryGetValue(crc, out mResourceItem)) { return(mResourceItem); } return(null); }
//根据资源全路径返回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); }
/// <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); }
//从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); } }
/// <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); }
/// <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); }
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); }
/// <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); }
//根据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); }
/// <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); }
/// <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); }
/// <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); } } }