/// <summary> /// 不需要实例化的资源卸载,根据路径 /// </summary> /// <param UIName="path"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> internal bool ReleaseResource(string path, uint crc, bool destroyRes = true) { if (string.IsNullOrEmpty(path)) { Debug.LogError("释放资源的路径为null"); return(false); } if (crc == 0) { crc = Crc32.GetCrc32(path); } ResItem item = null; if (!_UsededResCacheDic.TryGetValue(crc, out item) || item == null) { Debug.LogError("不存在该资源 Path: " + path + " 可能多次释放"); return(false); } item.RefCount.Decrease(); DestroyResourceItem(item, destroyRes); return(true); }
/// <summary> /// 预加载资源 /// </summary> public void PreloadResource <T>(string path, uint crc = 0, ResLoadMode mode = ResLoadMode.Null) where T : UnityEngine.Object { if (string.IsNullOrEmpty(path)) { return; } if (mode == ResLoadMode.Null) { mode = LoadMode(ref path); } if (crc == 0) { crc = Crc32.GetCrc32(path); } ResItem item = GetCacheResouceItem(crc, 0); if (item != null) { return; } //资源加载 item = LoadResource <T>(mode, path, crc); //缓存 CacheResource(path, ref item, crc); //跳场景不清空缓存 item.Clear = false; ReleaseResource(item.Obj, false); }
public ResItem LoadResourceAssetBundle(uint crc) { ResItem item = null; if (!_ResouceItemDic.TryGetValue(crc, out item) || item == null) { return(item); } if (item.AssetBundle != null) { 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> /// 根据ResourceObj 卸载资源 /// </summary> /// <param UIName="resObj"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> internal bool ReleaseResourceAsset(ResouceObj resObj, int assetHelpHash, int poolCacheCount, bool destroyOjb = false) { if (resObj == null) { return(false); } ResItem item = null; if (!_UsededResCacheDic.TryGetValue(resObj.Crc, out item) || item == null) { Debug.LogError("不存在该资源 anme: " + resObj.CloneObj.name + " 可能多次释放"); return(false); } RemoveObjAsset(item.Crc, assetHelpHash); GameObject.Destroy(resObj.CloneObj); if (poolCacheCount == 0 && resObj.ResItem.RefCount.count == 1) { resObj.ResItem.RefCount.Decrease(); DestroyResourceItem(item, destroyOjb); } return(true); }
/// <summary> /// 根据crc查找ResourceItem /// </summary> /// <param UIName="crc"></param> /// <returns></returns> public ResItem FindResourceItem(uint crc) { ResItem item = null; _ResouceItemDic.TryGetValue(crc, out item); return(item); }
/// <summary> /// 同步资源加载 , 外部直接调用,仅加载不需要实例化的资源,例如Texture,Audio /// </summary> /// <typeparam UIName="T"></typeparam> /// <param UIName="path"></param> /// <returns></returns> internal T LoadResource <T>(string path, uint crc = 0, ResLoadMode mode = ResLoadMode.Null) where T : UnityEngine.Object { if (string.IsNullOrEmpty(path)) { Debug.LogError("路径为null"); return(null); } if (mode == ResLoadMode.Null) { mode = LoadMode(ref path); } if (crc == 0) { crc = Crc32.GetCrc32(path); } ResItem item = GetCacheResouceItem(crc); if (item != null) { return(item.Obj as T); } //资源加载 item = LoadResource <T>(mode, path, crc); CacheResource(path, ref item, crc); //Debug.Log(item.Obj.name); return(item.Obj as T); }
/// <summary> /// 异步加载资源 (仅仅是不需要实例化的资源) /// </summary> private void AsyncLoadResource <T>(string path, OnAsyncObjFinish onFinish, uint crc = 0, ResLoadMode mode = ResLoadMode.Null, LoadResPriority priority = LoadResPriority.Res_Slow, params object[] paramValues) where T : UnityEngine.Object { if (mode == ResLoadMode.Null) { mode = LoadMode(ref path); } if (crc == 0) { crc = Crc32.GetCrc32(path); } ResItem item = GetCacheResouceItem(crc); if (item != null) { if (onFinish != null) { onFinish(path, item.Obj, paramValues); } return; } //判断是否在加载中 AsyncLoadResParam param = null; if (!_LoadingAssetDic.TryGetValue(crc, out param) || param == null) { param = _AsyncLoadResParamPool.Spawn(true); param.Crc = crc; param.Path = path; param.Priority = priority; param.ResType = typeof(T); param.LoadMode = JudgeLoadMode(mode); _LoadingAssetDic.Add(crc, param); _LoadingAssetList[(int)priority].Add(param); } //回调列表里面加回调 AsyncCallBack callBack = _AsyncCallBackPool.Spawn(true); callBack.OnObjFinish = onFinish; if (paramValues != null && paramValues.Length > 0) { foreach (object value in paramValues) { callBack.Params.Add(value); } } param.CallBackList.Add(callBack); }
public void Reset() { Crc = 0; ResItem = null; CloneObj = null; ClearByChangeScene = true; Guid = 0; AlreadyRelease = false; SetParent = false; OnFinish = null; ParamList.Clear(); }
/// <summary> /// 卸载 不需要的实例化资源 根据对象 /// </summary> /// <param UIName="obj"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> private bool ReleaseResource(ResItem item, bool destroyRes = true) { if (item == null) { Debug.LogError("不存在该资源 obj: " + item.Obj.name + " 可能多次释放"); return(false); } item.RefCount.Decrease(); DestroyResourceItem(item, destroyRes); return(true); }
/// <summary> /// 缓存太多, 清除最早没有使用的资源 /// </summary> protected void WashOut() { // 当前内存使用大于80% 时候 清除最早没有使用的资源 //当大于好吃个数时进行一半释放 while (_NoRefrenceAssetMapList.Size() >= _MaxCacheCount) { for (int i = 0; i < _MaxCacheCount / 2; i++) { ResItem item = _NoRefrenceAssetMapList.Back(); DestroyResourceItem(item, true); } } }
/// <summary> /// 从缓存中获取resourceItem /// </summary> /// <param UIName="crc"></param> /// <param UIName="addRefcount"></param> /// <returns></returns> ResItem GetCacheResouceItem(uint crc, int addRefcount = 1) { ResItem item = null; if (_UsededResCacheDic.TryGetValue(crc, out item) && item != null) { if (item.RefCount.count == 0) { item.RefCount.Increase(addRefcount); } } return(item); }
/// <summary> /// 释放资源 /// </summary> /// <param UIName="item"></param> public void ReleaseAsset(ResItem 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); }
/// <summary> /// 卸载 不需要的实例化资源 根据对象 /// </summary> /// <param UIName="obj"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> private bool ReleaseResource(Object obj, bool destroyRes = true) { if (obj == null) { Debug.LogError("释放资源的对象为null"); return(false); } ResItem item = null; foreach (var res in _UsededResCacheDic.Values) { if (res.Guid == obj.GetInstanceID()) { item = res; } } return(ReleaseResource(item, destroyRes)); }
/// <summary> /// 针对ObjectManager的异步加载接口 /// </summary> /// <param UIName="path"></param> /// <param UIName="resObj"></param> /// <param UIName="dealFinish"></param> /// <param UIName="priority"></param> internal void AsyncLoadResource(string path, ResLoadMode mode, ResouceObj resObj, OnAsyncFinish dealFinish, LoadResPriority priority) { ResItem item = GetCacheResouceItem(resObj.Crc); if (item != null) { resObj.ResItem = item; if (dealFinish != null) { dealFinish(path, resObj); } return; } //判断是否在加载中 AsyncLoadResParam param = null; if (!_LoadingAssetDic.TryGetValue(resObj.Crc, out param) || param == null) { param = _AsyncLoadResParamPool.Spawn(true); param.Crc = resObj.Crc; if (mode == ResLoadMode.Ab) { param.LoadMode = LoadResMode.AssetBundle; } else { param.LoadMode = LoadResMode.Resource; } param.Path = path; param.Priority = priority; _LoadingAssetDic.Add(resObj.Crc, param); _LoadingAssetList[(int)priority].Add(param); } //回调列表里面加回调 AsyncCallBack callBack = _AsyncCallBackPool.Spawn(true); callBack.OnFinish = dealFinish; callBack.ResObj = resObj; param.CallBackList.Add(callBack); }
/// <summary> /// 加载AB配置表 /// </summary> /// <returns></returns> public void LoadAssetBundleConfig() { _ResouceItemDic.Clear(); string configPath = AssetBundlePath + "/assetbundleconfig"; #if UNITY_EDITOR if (!File.Exists(configPath)) { Debug.LogError("assetbundleconfig 文件不存在, 没有进行打包 path " + configPath); } #endif AssetBundle configAB = AssetBundle.LoadFromFile(configPath); TextAsset textAsset = configAB.LoadAsset <TextAsset>("AssetBundleConfig.bytes"); AssetBundleConfig config; using (MemoryStream ms = new MemoryStream(textAsset.bytes)) { BinaryFormatter bf = new BinaryFormatter(); config = (AssetBundleConfig)bf.Deserialize(ms); } for (int i = 0; i < config.ABList.Count; i++) { ABBase abBase = config.ABList[i]; ResItem item = new ResItem(); item.Crc = abBase.Crc; item.AssetName = abBase.AssetName; item.ABName = abBase.ABName; item.DependAssetBundle = abBase.ABDependence; if (_ResouceItemDic.ContainsKey(item.Crc)) { Debug.LogError("重复的Crc 资源名:" + item.AssetName + "ab包名:" + item.ABName); } else { _ResouceItemDic.Add(item.Crc, item); } } }
/// <summary> /// 不需要实例化的资源卸载,根据路径 AssetHelp /// </summary> /// <param UIName="path"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> internal bool ReleaseAsset(uint crc, int count = 1) { ResItem item = null; if (!_UsededResCacheDic.TryGetValue(crc, out item) || item == null) { return(false); } //预加载没有使用的资源 引用为0 if (item.RefCount.count > 0) { if (count > item.RefCount.count) { count = item.RefCount.count; } item.RefCount.Decrease(count); } DestroyResourceItem(item, true); return(true); }
/// <summary> /// 缓存加载的资源 /// </summary> /// <param UIName="path"></param> /// <param UIName="item"></param> /// <param UIName="crc"></param> /// <param UIName="obj"></param> /// <param UIName="addrefcount"></param> void CacheResource(string path, ref ResItem item, uint crc, int addrefcount = 1) { //缓存太多,清除最早没有使用的资源 WashOut(); if (item == null) { Debug.LogError("没有创建ResItem Path : " + path); } item.RefCount.Increase(addrefcount); ResItem oldItem = null; if (_UsededResCacheDic.TryGetValue(crc, out oldItem)) { _UsededResCacheDic[item.Crc] = item; } else { _UsededResCacheDic.Add(item.Crc, item); } }
/// <summary> /// 卸载 不需要的实例化资源 根据对象 /// </summary> /// <param UIName="obj"></param> /// <param UIName="destroyOjb"></param> /// <returns></returns> internal bool ReleaseResourceAsset(UnityEngine.Object obj, int assetHelpHash, bool destroyRes = true) { if (obj == null) { Debug.LogError("释放资源的对象为null"); return(false); } ResItem item = null; foreach (var res in _UsededResCacheDic.Values) { if (res.Guid == obj.GetInstanceID()) { item = res; } } uint crc = item.Crc; RemoveResAsset(crc, assetHelpHash); return(ReleaseResource(item, destroyRes)); }
/// <summary> /// 回收一个资源 /// </summary> /// <param UIName="item"></param> /// <param UIName="destroy"></param> internal void DestroyResourceItem(ResItem item, bool destroyCache = false) { Debug.Log(item.RefCount.count + "资源卸载"); if (item == null || item.RefCount.count > 0) { return; } if (!destroyCache) { _NoRefrenceAssetMapList.InsertToHead(item); return; } if (!_UsededResCacheDic.Remove(item.Crc)) { return; } _NoRefrenceAssetMapList.Remove(item); //释放AssetBundle引用 AssetBundleMgr.Instance.ReleaseAsset(item); //清空资源对应的对象池资源 ObjManager.Instance.ClearPoolObject(item.Crc); if (item.Obj != null) { item.Obj = null; #if UNITY_EDITOR Debug.Log("卸载完成"); Resources.UnloadUnusedAssets(); #endif } }
/// <summary> /// 同步加载资源,针对ObjectManager的接口 /// </summary> /// <param UIName="path"></param> /// <param UIName="resObj"></param> /// <returns></returns> public ResouceObj LoadRessource(string path, ResLoadMode mode, ResouceObj resObj) { if (resObj == null) { return(null); } uint crc = resObj.Crc == 0 ? Crc32.GetCrc32(path) : resObj.Crc; ResItem item = GetCacheResouceItem(crc); if (item != null) { resObj.ResItem = item; return(resObj); } item = LoadResource <Object>(mode, path, crc); CacheResource(path, ref item, crc); resObj.ResItem = item; item.Clear = resObj.ClearByChangeScene; return(resObj); }
private ResItem LoadResource <T>(ResLoadMode mode, string path, uint crc) where T : UnityEngine.Object { T obj = null; ResItem item = null; #if UNITY_EDITOR if (IsEditorLoadMode) { if (JudgeLoadMode(mode) == LoadResMode.Resource) { obj = Resources.Load <T>(path); } else { obj = LoadAssetByEditor <T>(path); } } #endif if (obj == null) { if (JudgeLoadMode(mode) == LoadResMode.Resource) { obj = Resources.Load <T>(path); } else { item = AssetBundleMgr.Instance.LoadResourceAssetBundle(crc); if (item != null && item.AssetBundle != null) { if (item.Obj != null) { obj = item.Obj as T; } else { Debug.Log("AssetBundle模型下加载"); obj = item.AssetBundle.LoadAsset <T>(item.AssetName); } } else { Debug.LogErrorFormat("加载AssetBundle失败 : 不能从AssetBundleConfig中找到 Path :{0}", path); } } } if (obj == null) { Debug.LogError("加载资源失败,请检查资源[加载模式] mode ;" + loadResMode + " [路径] Path:" + path); } if (item == null) { item = new ResItem(); } item.Crc = crc; item.Obj = obj; if (obj) { item.Guid = obj.GetInstanceID(); } return(item); }
/// <summary> /// 异步加载 /// </summary> /// <returns></returns> IEnumerator AsyncLoadCor() { List <AsyncCallBack> callBackList = null; //上一次yield的时间 long lastYieldTime = System.DateTime.Now.Ticks; while (true) { bool haveYield = false; for (int i = 0; i < (int)LoadResPriority.Res_Num; i++) { if (_LoadingAssetList[(int)LoadResPriority.Res_Hight].Count > 0) { i = (int)LoadResPriority.Res_Hight; } else if (_LoadingAssetList[(int)LoadResPriority.Res_Middle].Count > 0) { i = (int)LoadResPriority.Res_Middle; } List <AsyncLoadResParam> loadingList = _LoadingAssetList[i]; if (loadingList.Count <= 0) { continue; } AsyncLoadResParam loadingItem = loadingList[0]; loadingList.RemoveAt(0); callBackList = loadingItem.CallBackList; Object obj = null; ResItem item = null; #if UNITY_EDITOR if (IsEditorLoadMode) { if (item == null) { item = new ResItem(); item.Crc = loadingItem.Crc; } if (loadingItem.LoadMode == ResKit.LoadResMode.Resource) { ResourceRequest resRequest = null; if (loadingItem.ResType == typeof(Sprite)) { resRequest = Resources.LoadAsync <Sprite>(loadingItem.Path); } else { resRequest = Resources.LoadAsync <Object>(loadingItem.Path); } yield return(resRequest); if (resRequest.isDone) { obj = resRequest.asset; } lastYieldTime = System.DateTime.Now.Ticks; } else { if (loadingItem.ResType == typeof(Sprite)) { obj = LoadAssetByEditor <Sprite>(loadingItem.Path); } else { obj = LoadAssetByEditor <Object>(loadingItem.Path); } //模拟异步加载 yield return(new WaitForSeconds(0.2f)); } } #endif if (obj == null) { if (loadingItem.LoadMode == ResKit.LoadResMode.Resource) { if (item == null) { item = new ResItem(); item.Crc = loadingItem.Crc; } ResourceRequest resRequest = null; if (loadingItem.ResType == typeof(Sprite)) { resRequest = Resources.LoadAsync <Sprite>(loadingItem.Path); } else { resRequest = Resources.LoadAsync <Object>(loadingItem.Path); } yield return(resRequest); if (resRequest.isDone) { obj = resRequest.asset; } lastYieldTime = System.DateTime.Now.Ticks; } else { item = AssetBundleMgr.Instance.LoadResourceAssetBundle(loadingItem.Crc); if (item != null && item.AssetBundle != null) { AssetBundleRequest abRequest = null; if (loadingItem.ResType == typeof(Sprite)) { //是图片资源 abRequest = item.AssetBundle.LoadAssetAsync <Sprite>(item.AssetName); } else { //不是图片资源 abRequest = item.AssetBundle.LoadAssetAsync(item.AssetName); } yield return(abRequest); if (abRequest.isDone) { obj = abRequest.asset; } lastYieldTime = System.DateTime.Now.Ticks; } else { Debug.LogErrorFormat("加载AssetBundle失败 : 不能从AssetBundleConfig中找到 Path :{0}", loadingItem.Path); } } } item.Crc = loadingItem.Crc; item.Obj = obj; item.Guid = obj.GetInstanceID(); CacheResource(loadingItem.Path, ref item, loadingItem.Crc, callBackList.Count); for (int j = 0; j < callBackList.Count; j++) { AsyncCallBack callBack = callBackList[j]; if (callBack != null && callBack.OnFinish != null && callBack.ResObj != null) { ResouceObj tempResObj = callBack.ResObj; tempResObj.ResItem = item; callBack.OnFinish(loadingItem.Path, tempResObj, tempResObj.ParamValues); callBack.OnFinish = null; tempResObj = null; } if (callBack != null && callBack.OnObjFinish != null) { callBack.OnObjFinish(loadingItem.Path, obj, callBack.ParamValues); callBack.OnObjFinish = null; } callBack.Reset(); _AsyncCallBackPool.Recycle(callBack); } obj = null; callBackList.Clear(); _LoadingAssetDic.Remove(loadingItem.Crc); loadingItem.Reset(); _AsyncLoadResParamPool.Recycle(loadingItem); if (System.DateTime.Now.Ticks - lastYieldTime > _MaxLoadResTime) { yield return(null); lastYieldTime = System.DateTime.Now.Ticks; haveYield = true; } } //大于 _MaxLoadResTime 时间才等待一帧 if (!haveYield || System.DateTime.Now.Ticks - lastYieldTime > _MaxLoadResTime) { lastYieldTime = System.DateTime.Now.Ticks; yield return(null); } } }