/// <summary> /// 回收一个资源 /// </summary> /// <param name="item"></param> /// <param name="destroy"></param> protected void DestroyResouceItem(TResouceItem item, bool destroyCache = false) { if (item == null || item.RefCount > 0) { return; } if (!destroyCache) { mNoRefrenceAssetMapList.InsertToHead(item); return; } if (!mAssetDic.Remove(item.Crc)) { return; } mNoRefrenceAssetMapList.Remove(item); // 释放assetbundle引用 AssetBundleManager.Instance.ReleaseAsset(item); //清空资源对应的对象池 ObjectManager.Instance.ClearPoolObject(item.Crc); if (item.Obj != null) { item.Obj = null; #if UNITY_EDITOR Resources.UnloadUnusedAssets(); #endif } }
/// <summary> /// 根据crc查找ResourceItem /// </summary> /// <param name="crc"></param> /// <returns></returns> public TResouceItem FindResouceItem(uint crc) { TResouceItem item = null; mResouceItemDic.TryGetValue(crc, out item); return(item); }
/// <summary> /// 针对ObjectManager异步加载的接口 /// </summary> /// <param name="path"></param> /// <param name="resObj"></param> /// <param name="dealfinish"></param> /// <param name="priority"></param> public void AsyncLoadResouce(string path, TResouceObj resObj, OnAsyncFinish dealfinish, LoadResPriority priority) { TResouceItem item = GetCacheResouceItem(resObj.Crc); if (item != null) { resObj.ResItem = item; dealfinish?.Invoke(path, resObj); } //判断是否在加载中 TAsyncLoadResParam para = null; if (!mLoadingAssetDic.TryGetValue(resObj.Crc, out para) || para == null) { para = mAsyncLoadResParamPool.Allocate(); para.Crc = resObj.Crc; para.Path = path; para.Priority = priority; mLoadingAssetDic.Add(resObj.Crc, para); mLoadingAssetList[(int)priority].Add(para); } //往回调列表里面加回调 TAsyncCallBack callBack = mAsyncCallBackPool.Allocate(); callBack.DealFinish = dealfinish; callBack.ResObj = resObj; para.CallbackList.Add(callBack); }
/// <summary> /// 缓存加载的资源 /// </summary> /// <param name="path"></param> /// <param name="item"></param> /// <param name="crc"></param> /// <param name="obj"></param> /// <param name="addrefcount"></param> void CacheResouce(string path, ref TResouceItem item, uint crc, Object obj, int addrefcount = 1) { //缓存太多,清除最早没有使用的资源 WashOut(); if (item == null) { Debug.LogError("ResourceItem is null,path:" + path); } if (obj == null) { Debug.LogError("Resource Fail:" + path); } item.Obj = obj; item.Guid = obj.GetInstanceID(); item.LastUserTime = Time.realtimeSinceStartup; item.RefCount += addrefcount; TResouceItem oldItem = null; if (mAssetDic.TryGetValue(item.Crc, out oldItem)) { mAssetDic[item.Crc] = item; } else { mAssetDic.Add(item.Crc, item); } }
/// <summary> /// 同步资源加载,外部直接调用,仅加载不需要实例化的资源,例如Texture,音频等等 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="path"></param> /// <returns></returns> public T LoadResouce <T>(string path) where T : UnityEngine.Object { if (string.IsNullOrEmpty(path)) { return(null); } uint crc = CRC32.GetCRC32(path); TResouceItem item = GetCacheResouceItem(crc); if (item != null) { return(item.Obj as T); } T obj = null; #if UNITY_EDITOR if (!AppConfig.UseAssetBundle) { item = AssetBundleManager.Instance.FindResouceItem(crc); if (item != null && item.AssetBundle != null) { if (item.Obj != null) { obj = (T)item.Obj; } else { obj = item.AssetBundle.LoadAsset <T>(item.AssetName); } } else { if (item == null) { item = new TResouceItem(); item.Crc = crc; } obj = LoadAssetByEditor <T>(path); } } #endif if (obj == null) { item = AssetBundleManager.Instance.LoadResouceAssetBundle(crc); if (item != null && item.AssetBundle != null) { if (item.Obj != null) { obj = item.Obj as T; } else { obj = item.AssetBundle.LoadAsset <T>(item.AssetName); } } } CacheResouce(path, ref item, crc, obj); return(obj); }
/// <summary> /// 同步资源加载,外部直接调用,仅加载不需要实例化的资源,例如Texture,音频等 /// </summary> /// <param name="path"></param> /// <param name="resObj"></param> /// <returns></returns> public TResouceObj LoadResouce(string path, TResouceObj resObj) { if (resObj == null) { return(null); } uint crc = resObj.Crc == 0 ? CRC32.GetCRC32(path) : resObj.Crc; TResouceItem item = GetCacheResouceItem(crc); if (item != null) { resObj.ResItem = item; return(resObj); } Object obj = null; #if UNITY_EDITOR if (!AppConfig.UseAssetBundle) { item = AssetBundleManager.Instance.FindResouceItem(crc); if (item != null && item.Obj != null) { obj = item.Obj as Object; } else { if (item == null) { item = new TResouceItem(); item.Crc = crc; } obj = LoadAssetByEditor <Object>(path); } } #endif if (obj == null) { item = AssetBundleManager.Instance.LoadResouceAssetBundle(crc); if (item != null && item.AssetBundle != null) { if (item.Obj != null) { obj = item.Obj as Object; } else { obj = item.AssetBundle.LoadAsset <Object>(item.AssetName); } } } CacheResouce(path, ref item, crc, obj); resObj.ResItem = item; item.Clear = resObj.Clear; return(resObj); }
/// <summary> /// 预加载资源 /// </summary> /// <param name="path"></param> public void PreloadRes(string path) { if (string.IsNullOrEmpty(path)) { return; } uint crc = CRC32.GetCRC32(path); TResouceItem item = GetCacheResouceItem(crc, 0); if (item != null) { return; } Object obj = null; #if UNITY_EDITOR if (!AppConfig.UseAssetBundle) { item = AssetBundleManager.Instance.FindResouceItem(crc); if (item != null && item.Obj != null) { obj = item.Obj as Object; } else { if (item == null) { item = new TResouceItem(); item.Crc = crc; } obj = LoadAssetByEditor <Object>(path); } } #endif if (obj == null) { item = AssetBundleManager.Instance.LoadResouceAssetBundle(crc); if (item != null && item.AssetBundle != null) { if (item.Obj != null) { obj = item.Obj; } else { obj = item.AssetBundle.LoadAsset <Object>(item.AssetName); } } } CacheResouce(path, ref item, crc, obj); //跳场景不清空缓存 item.Clear = false; ReleaseResouce(obj, false); }
/// <summary> /// 根据路径减少引用计数 /// </summary> /// <param name="crc"></param> /// <param name="count"></param> /// <returns></returns> public int DecreaseResouceRef(uint crc = 0, int count = 1) { TResouceItem item = null; if (!mAssetDic.TryGetValue(crc, out item) || item == null) { return(0); } item.RefCount -= count; return(item.RefCount); }
/// <summary> /// 缓存太多,清除最早没有使用的资源 /// </summary> protected void WashOut() { //当大于缓存个数时,进行一半释放 while (mNoRefrenceAssetMapList.Size() >= MAXCACHECOUNT) { for (int i = 0; i < MAXCACHECOUNT / 2; i++) { TResouceItem item = mNoRefrenceAssetMapList.Back(); DestroyResouceItem(item, true); } } }
/// <summary> /// 根据path增加引用计数 /// </summary> /// <param name="crc"></param> /// <param name="count"></param> /// <returns></returns> public int IncreaseResouceRef(uint crc = 0, int count = 1) { TResouceItem item = null; if (!mAssetDic.TryGetValue(crc, out item) || item == null) { return(0); } item.RefCount += count; item.LastUserTime = Time.realtimeSinceStartup; return(item.RefCount); }
/// <summary> /// 从资源池获取缓存资源 /// </summary> /// <param name="crc"></param> /// <param name="addrefcount"></param> /// <returns></returns> TResouceItem GetCacheResouceItem(uint crc, int addrefcount = 1) { TResouceItem item = null; if (mAssetDic.TryGetValue(crc, out item)) { if (item != null) { item.RefCount += addrefcount; item.LastUserTime = Time.realtimeSinceStartup; } } return(item); }
/// <summary> /// 释放资源 /// </summary> /// <param name="item"></param> public void ReleaseAsset(TResouceItem item) { if (item == null) { return; } if (item.DependAssetBundle != null && item.DependAssetBundle.Count > 0) { for (int i = 0; i < item.DependAssetBundle.Count; i++) { UnLoadAssetBundle(item.DependAssetBundle[i]); } } UnLoadAssetBundle(item.AbName); }
public void Reset() { Crc = 0; CloneObj = null; Clear = true; Guid = 0; ResItem = null; Already = false; SetSceneParent = false; DealFinish = null; Param1 = null; Param2 = null; Param3 = null; OffData = null; }
/// <summary> /// 根据ResouceObj卸载资源 /// </summary> /// <param name="resObj"></param> /// <param name="destroyObj">是否将ResouceItem从缓存引用计数的资源列表中移除</param> /// <returns></returns> public bool ReleaseResouce(TResouceObj resObj, bool destroyObj = false) { if (resObj == null) { return(false); } TResouceItem item = null; if (!mAssetDic.TryGetValue(resObj.Crc, out item) || item == null) { Debug.LogError("AssetDic里不存在该资源:" + resObj.CloneObj.name + " 可能释放了多次"); } GameObject.Destroy(resObj.CloneObj); item.RefCount--; DestroyResouceItem(item, destroyObj); return(true); }
/// <summary> /// 不需要实例化的资源卸载,根据路径 /// </summary> /// <param name="path"></param> /// <param name="destroyObj"></param> /// <returns></returns> public bool ReleaseResouce(string path, bool destroyObj = false) { if (string.IsNullOrEmpty(path)) { return(false); } uint crc = CRC32.GetCRC32(path); TResouceItem item = null; if (!mAssetDic.TryGetValue(crc, out item) || null == item) { Debug.LogError("AssetDic里不存在资源" + path + "可能释放了多次"); } item.RefCount--; DestroyResouceItem(item, destroyObj); return(true); }
/// <summary> /// 加载Ab配置表 /// </summary> /// <returns></returns> public bool LoadAssetBundleConfig() { #if UNITY_EDITOR if (!AppConfig.UseAssetBundle) { return(false); } #endif mResouceItemDic.Clear(); string configPath = ABLoadPath + mAbConfigABName; string hotAbPath = HotPatchManager.Instance.ComputeABPath(mAbConfigABName); configPath = string.IsNullOrEmpty(hotAbPath) ? configPath : hotAbPath; byte[] bytes = AES.AESFileByteDecrypt(configPath, EdgeFrameworkConst.AESKEY); AssetBundle configAB = AssetBundle.LoadFromMemory(bytes); TextAsset textAsset = configAB.LoadAsset <TextAsset>(mAbConfigABName); if (textAsset == null) { Debug.LogError("AssetBundleConfig is no exist!"); return(false); } MemoryStream stream = new MemoryStream(textAsset.bytes); BinaryFormatter bf = new BinaryFormatter(); AssetBundleConfig config = (AssetBundleConfig)bf.Deserialize(stream); stream.Close(); for (int i = 0; i < config.AbList.Count; i++) { ABBase abBase = config.AbList[i]; TResouceItem item = new TResouceItem(); item.Crc = abBase.Crc; item.AssetName = abBase.AssetName; item.AbName = abBase.AbName; item.DependAssetBundle = abBase.AbDependce; if (mResouceItemDic.ContainsKey(item.Crc)) { Debug.LogError("重复的Crc:" + item.AssetName + "ab包名:" + item.AbName); } else { mResouceItemDic.Add(item.Crc, item); } } return(true); }
/// <summary> /// 异步加载资源(仅仅是不需要实例化的资源,例如音频,图片等) /// </summary> /// <param name="path"></param> /// <param name="dealFinish"></param> /// <param name="priority"></param> /// <param name="param1"></param> /// <param name="param2"></param> /// <param name="param3"></param> /// <param name="crc"></param> public void AsyncLoadResouce(string path, OnAsyncObjFinish dealFinish, LoadResPriority priority, bool isSprite = false, object param1 = null, object param2 = null, object param3 = null, uint crc = 0) { if (crc == 0) { crc = CRC32.GetCRC32(path); } TResouceItem item = GetCacheResouceItem(crc); if (item != null) { if (dealFinish != null) { dealFinish(path, item.Obj, param1, param2, param3); } return; } //判断是否在加载中 TAsyncLoadResParam para = null; if (!mLoadingAssetDic.TryGetValue(crc, out para) || para == null) { para = mAsyncLoadResParamPool.Allocate(); para.Crc = crc; para.Path = path; para.IsSprite = isSprite; para.Priority = priority; mLoadingAssetDic.Add(crc, para); mLoadingAssetList[(int)priority].Add(para); } //往回调列表里面加回调 TAsyncCallBack callBack = mAsyncCallBackPool.Allocate(); callBack.DealObjFinish = dealFinish; callBack.Param1 = param1; callBack.Param2 = param2; callBack.Param3 = param3; para.CallbackList.Add(callBack); }
/// <summary> /// 根据路径的crc加载中间类ResouceItem /// </summary> /// <param name="crc"></param> /// <returns></returns> public TResouceItem LoadResouceAssetBundle(uint crc) { TResouceItem item = null; if (!mResouceItemDic.TryGetValue(crc, out item) || item == null) { Debug.LogError(string.Format("LoadResourceAssetBundle Erro:can not find crc {0} in AssetBundleConfig", crc.ToString())); return(item); } //if (item.assetBundle != null) //{ // item.RefCount++; // return item; //} item.AssetBundle = LoadAssetBundle(item.AbName); if (item.DependAssetBundle != null) { for (int i = 0; i < item.DependAssetBundle.Count; i++) { LoadAssetBundle(item.DependAssetBundle[i]); } } return(item); }
/// <summary> /// 不需要实例化的资源卸载,根据对象 /// </summary> /// <param name="obj"></param> /// <param name="destroyObj"></param> /// <returns></returns> public bool ReleaseResouce(Object obj, bool destroyObj = false) { if (obj == null) { return(false); } TResouceItem item = null; foreach (TResouceItem res in mAssetDic.Values) { if (res.Guid == obj.GetInstanceID()) { item = res; } } if (item == null) { Debug.LogError("AssetDic里不存在资源" + obj.name + "可能释放了多次"); return(false); } item.RefCount--; DestroyResouceItem(item, destroyObj); return(true); }
/// <summary> /// 异步加载 /// </summary> /// <returns></returns> IEnumerator AsyncLoadCor() { List <TAsyncCallBack> callBackList = null; //上一次yild的时间 long lastYildTime = System.DateTime.Now.Ticks; while (true) { bool haveYield = false; for (int i = 0; i < (int)LoadResPriority.RES_NUM; i++) { if (mLoadingAssetList[(int)LoadResPriority.RES_HIGHT].Count > 0) { i = (int)LoadResPriority.RES_HIGHT; } else if (mLoadingAssetList[(int)LoadResPriority.RES_MIDDLE].Count > 0) { i = (int)LoadResPriority.RES_MIDDLE; } List <TAsyncLoadResParam> loadingList = mLoadingAssetList[i]; if (loadingList.Count <= 0) { continue; } TAsyncLoadResParam loadingItem = loadingList[0]; loadingList.RemoveAt(0); callBackList = loadingItem.CallbackList; Object obj = null; TResouceItem item = null; #if UNITY_EDITOR if (!AppConfig.UseAssetBundle) { if (loadingItem.IsSprite) { obj = LoadAssetByEditor <Sprite>(loadingItem.Path); } else { obj = LoadAssetByEditor <Object>(loadingItem.Path); } //模拟异步加载 yield return(new WaitForSeconds(0.5f)); item = AssetBundleManager.Instance.FindResouceItem(loadingItem.Crc); if (item == null) { item = new TResouceItem(); item.Crc = loadingItem.Crc; } } #endif if (obj == null) { item = AssetBundleManager.Instance.LoadResouceAssetBundle(loadingItem.Crc); if (item != null && item.AssetBundle != null) { AssetBundleRequest abRequest = null; if (loadingItem.IsSprite) { abRequest = item.AssetBundle.LoadAssetAsync <Sprite>(item.AssetName); } else { abRequest = item.AssetBundle.LoadAssetAsync(item.AssetName); } yield return(abRequest); if (abRequest.isDone) { obj = abRequest.asset; } lastYildTime = System.DateTime.Now.Ticks; } } CacheResouce(loadingItem.Path, ref item, loadingItem.Crc, obj, callBackList.Count); for (int j = 0; j < callBackList.Count; j++) { TAsyncCallBack callBack = callBackList[j]; if (callBack != null && callBack.DealFinish != null && callBack.ResObj != null) { TResouceObj tempResObj = callBack.ResObj; tempResObj.ResItem = item; callBack.DealFinish(loadingItem.Path, tempResObj, tempResObj.Param1, tempResObj.Param2, tempResObj.Param3); callBack.DealFinish = null; tempResObj = null; } if (callBack != null && callBack.DealObjFinish != null) { callBack.DealObjFinish(loadingItem.Path, obj, callBack.Param1, callBack.Param2, callBack.Param3); callBack.DealObjFinish = null; } callBack.Reset(); mAsyncCallBackPool.Recycle(callBack); } obj = null; callBackList.Clear(); mLoadingAssetDic.Remove(loadingItem.Crc); loadingItem.Reset(); mAsyncLoadResParamPool.Recycle(loadingItem); if (System.DateTime.Now.Ticks - lastYildTime > MAXLOADRESTIME) { yield return(null); lastYildTime = System.DateTime.Now.Ticks; haveYield = true; } } if (!haveYield || System.DateTime.Now.Ticks - lastYildTime > MAXLOADRESTIME) { lastYildTime = System.DateTime.Now.Ticks; yield return(null); } yield return(null); } }