public void ClearCacheByCrc(uint crc) { List <ResourceGameObject> tList = null; if (!m_resGoObjectPoolDic.TryGetValue(crc, out tList) || tList == null) { return; } for (int i = tList.Count - 1; i >= 0; i++) { ResourceGameObject resGo = tList[i]; if (resGo != null && resGo.IsClear) { tList.Remove(resGo); resGo.Reset(); m_resGoClassPool.Recycle(resGo); var guid = resGo.GoGuid; if (m_guidResGoDic.ContainsKey(guid)) { m_guidResGoDic.Remove(guid); } } } if (tList.Count <= 0) { if (m_resGoObjectPoolDic.ContainsKey(crc)) { m_resGoObjectPoolDic.Remove(crc); } } }
/// <summary> /// 在回收池查找有没有空闲的resGo /// </summary> private ResourceGameObject GetResGoFromRecycleDic(uint crc) { ResourceGameObject resGo = null; List <ResourceGameObject> tempList = null; if (m_resGoObjectPoolDic.TryGetValue(crc, out tempList) && tempList.Count > 0) { resGo = tempList[0]; tempList.RemoveAt(0); GameObject go = resGo.CloneGo; ResourcesManager.Instance.IncreaseResGoRefCount(resGo); //取出时,增加ABDataItem的引用计数 //判断go的是否被引用了,还有引用的话,要重置IsRecycle if (!System.Object.ReferenceEquals(go, null)) { resGo.IsRecycle = false; } #if UNITY_EDITOR if (go.name.EndsWith("(Recycle)")) { go.name = go.name.Replace("(Recycle)", ""); } if (!go.activeInHierarchy) { go.SetActive(true); } #endif } return(resGo); }
/// <summary> /// 内层异步加载完成的回调,用来实例化对象,并且执行外层的异步加载完成的回调 /// </summary> /// <param name="path"></param> /// <param name="resGo"></param> /// <param name="param1"></param> /// <param name="param2"></param> /// <param name="param3"></param> public void OnAsyncLoadResGoDealFinish(string path, ResourceGameObject resGo, object param1 = null, object param2 = null, object param3 = null) { if (resGo == null) { return; } if (resGo.ABDataItem == null) { Debug.LogError("没有加载ABDataItem,请检查ResourceManager中的协程方法"); return; } if (resGo.ABDataItem.Obj != null) { resGo.CloneGo = GameObject.Instantiate(resGo.ABDataItem.Obj) as GameObject; resGo.GoGuid = resGo.CloneGo.GetInstanceID(); m_cancelIdResGoDic.Remove(resGo.CancelId); if (!m_guidResGoDic.ContainsKey(resGo.GoGuid)) { m_guidResGoDic.Add(resGo.GoGuid, resGo); } if (resGo.DealFinish != null) { resGo.DealFinish(path, resGo.CloneGo, param1, param2, param3); } } }
/// <summary> /// 同步加载实例化对象 /// </summary> /// <param name="path"></param> /// <param name="isSetSceneTr"></param> /// <param name="isClear"></param> /// <returns></returns> public GameObject InstantiateGameObj(string path, bool isSetSceneTr = true, bool isClear = true) { uint pathCrc = Crc32.GetCRC32(path); ResourceGameObject resGo = GetResGoFromRecycleDic(pathCrc); if (resGo == null) { resGo = m_resGoClassPool.Create(true); resGo.Crc = pathCrc; //加载resGo的abDataItem等 ResourcesManager.Instance.LoadResourceGameObj(path, ref resGo); if (resGo.ABDataItem.Obj != null) { resGo.CloneGo = GameObject.Instantiate(resGo.ABDataItem.Obj) as GameObject; } resGo.IsClear = isClear; resGo.GoGuid = resGo.CloneGo.GetInstanceID(); if (!m_guidResGoDic.ContainsKey(resGo.GoGuid)) { m_guidResGoDic.Add(resGo.GoGuid, resGo); } } if (isSetSceneTr) { resGo.CloneGo.transform.SetParent(SceneTr); } return(resGo.CloneGo); }
/// <summary> /// 给ObjectsManager提供的接口,加载resGo /// </summary> public void AsyncLoadResource(string path, ResourceGameObject resGo, AsyncLoadResGoDealFinish resGoDealFinish) { uint pathCrc = Crc32.GetCRC32(path); AssetBundleDataItem dataItem = GetCacheABDataItem(pathCrc); if (dataItem != null) { resGo.ABDataItem = dataItem; if (resGoDealFinish != null) { resGoDealFinish(path, resGo, resGo.Param1, resGo.Param2, resGo.Param3); } return; } AsyncLoadDataItem asyncDataItem = null; if (!m_asyncLoadingItemDic.TryGetValue(pathCrc, out asyncDataItem) && asyncDataItem == null) { asyncDataItem = m_asyncDataItemPool.Create(true); asyncDataItem.Path = path; asyncDataItem.Crc = pathCrc; asyncDataItem.Priority = resGo.Priority; m_asyncLoadItemListArray[(int)resGo.Priority].Add(asyncDataItem); m_asyncLoadingItemDic.Add(pathCrc, asyncDataItem); } AsyncLoadCallBack callBack = m_asyncCallBackPool.Create(true); callBack.ResGoDealFinish = resGoDealFinish; callBack.resGo = resGo; asyncDataItem.CallBackList.Add(callBack); }
//----------------------------------------------------------------------- #region 提供给ObjectsManager的接口 /// <summary> /// 给ObjectsManager提供的接口:加载ResourceObj的ABDataItem等 /// </summary> /// <param name="path"></param> /// <param name="resObj"></param> public bool LoadResourceGameObj(string path, ref ResourceGameObject resObj) { if (resObj == null || string.IsNullOrEmpty(path)) { return(false); } uint pathCrc = Crc32.GetCRC32(path); AssetBundleDataItem dataItem = null; dataItem = GetCacheABDataItem(pathCrc); if (dataItem != null && dataItem.Obj != null) { resObj.ABDataItem = dataItem; return(true); } Object obj = null; #if UNITY_EDITOR if (!GameRoot.m_UseAssetBundleInEditor) { dataItem = AssetBundleManager.Instance.GetABDataItem(pathCrc); if (dataItem != null && dataItem.Obj != null) { obj = dataItem.Obj; } else { obj = LoadABDataItemInEditorMode <Object>(path); } if (dataItem == null) { dataItem = new AssetBundleDataItem(); dataItem.Crc = pathCrc; } } #endif if (obj == null) { dataItem = AssetBundleManager.Instance.LoadABDataItem(pathCrc); if (dataItem != null && dataItem.AB != null) { if (dataItem.Obj != null) { obj = dataItem.Obj; } else { obj = dataItem.AB.LoadAsset <Object>(dataItem.AssetName); } } } CacheABDataItem(path, ref dataItem, obj); resObj.ABDataItem = dataItem; dataItem.IsClear = resObj.IsClear; return(true); }
public bool CancelAsyncLoad(ResourceGameObject resGo) { AsyncLoadDataItem asyncDataItem = null; //判断正在加载的字典中是否包含asyncDataItem, 并且没有进入异步的for循环 if (m_asyncLoadingItemDic.TryGetValue(resGo.Crc, out asyncDataItem) && m_asyncLoadItemListArray[(int)resGo.Priority].Contains(asyncDataItem)) { //重置callbackList var callBackList = asyncDataItem.CallBackList; for (int i = callBackList.Count - 1; i >= 0; i--) { //回收回调(可能有多个回调) AsyncLoadCallBack callBack = callBackList[i]; if (callBack != null) { callBack.Reset(); callBackList.Remove(callBack); m_asyncCallBackPool.Recycle(callBack); } } if (callBackList.Count <= 0) { //只有全部回调都移除了才能真正取消异步加载 asyncDataItem.Reset(); m_asyncLoadingItemDic.Remove(resGo.Crc); m_asyncLoadItemListArray[(int)resGo.Priority].Remove(asyncDataItem); m_asyncDataItemPool.Recycle(asyncDataItem); return(true); } } return(false); }
public void Reset() { ResGoDealFinish = null; resGo = null; DealFinish = null; Param1 = null; Param2 = null; Param3 = null; }
/// <summary> /// 根据resGo释放资源 /// </summary> public bool ReleaseResources(ResourceGameObject resGo, bool isDestroy = true) { if (resGo == null) { return(false); } AssetBundleDataItem dataItem = m_crcAssetDic[resGo.Crc]; if (dataItem == null) { Debug.LogError(string.Format("不存在对应pathCrc的ABDataItem: {0}, {1}", resGo.Crc, resGo.CloneGo.name)); return(false); } //销毁对象 GameObject.Destroy(resGo.CloneGo); dataItem.RefCount--; ReleaseABDataItem(dataItem, isDestroy); return(true); }
/// <summary> /// 异步加载实例化对象 /// </summary> /// <param name="path"></param> /// <param name="dealFinish">外层调用时传入的加载完成回调</param> /// <param name="priority"></param> /// <param name="isSetSceneTr">是否设置到场景节点</param> /// <param name="param1"></param> /// <param name="param2"></param> /// <param name="param3"></param> /// <param name="isClear">是否跳转场景销毁/清除</param> public long AsyncInstantiateGameObj(string path, AsyncLoadDealFinish dealFinish, AsyncLoadPriority priority, bool isSetSceneTr = false, object param1 = null, object param2 = null, object param3 = null, bool isClear = true) { uint pathCrc = Crc32.GetCRC32(path); ResourceGameObject resGo = GetResGoFromRecycleDic(pathCrc); if (resGo != null) { if (isSetSceneTr) { resGo.CloneGo.transform.SetParent(SceneTr); } if (dealFinish != null) { dealFinish(path, resGo.CloneGo, param1, param2, param3); } return(resGo.CancelId); } resGo = m_resGoClassPool.Create(true); resGo.Crc = pathCrc; resGo.IsClear = isClear; resGo.IsSetSceneTr = isSetSceneTr; resGo.Priority = priority; resGo.DealFinish = dealFinish; resGo.Param1 = param1; resGo.Param2 = param2; resGo.Param3 = param3; ResourcesManager.Instance.AsyncLoadResource(path, resGo, OnAsyncLoadResGoDealFinish); resGo.CancelId = CreateCancelId(); m_cancelIdResGoDic.Add(CancelId, resGo); return(resGo.CancelId); }
/// <summary> /// 清空对象池 /// </summary> public void ClearCache() { List <uint> uintList = new List <uint>(); foreach (uint crc in m_resGoObjectPoolDic.Keys) { List <ResourceGameObject> tList = m_resGoObjectPoolDic[crc]; for (int i = tList.Count - 1; i >= 0; i++) { ResourceGameObject resGo = tList[i]; if (resGo != null && resGo.IsClear) { GameObject.Destroy(resGo.CloneGo); tList.Remove(resGo); resGo.Reset(); m_guidResGoDic.Remove(resGo.CloneGo.GetInstanceID()); m_resGoClassPool.Recycle(resGo); } if (tList.Count <= 0) { uintList.Add(crc); } } } for (int i = 0; i < uintList.Count; i++) { if (m_resGoObjectPoolDic.ContainsKey(uintList[i])) { m_resGoObjectPoolDic.Remove(uintList[i]); } } uintList.Clear(); }
/// <summary> /// 根据go回收 /// </summary> /// <param name="go"></param> /// <param name="maxRecycleCount">最大的回收数量, -1表示不限制数量</param> /// <param name="isDestroy">是否销毁</param> /// <param name="toParent">是否设置到父节点(RecycleObjectsTr:对象池节点)</param> public void ReleaseGameObject(GameObject go, int maxRecycleCount = -1, bool isDestroy = false, bool toParent = false) { if (go == null) { Debug.Log("需要释放的go为null"); return; } ResourceGameObject resGo = null; int tempId = go.GetInstanceID(); if (!m_guidResGoDic.TryGetValue(tempId, out resGo) || resGo == null) { Debug.Log("此回收对象非ObjectsManager创建,找不到对应Guid的ResourceObj"); return; } if (maxRecycleCount == 0) //不回收 { m_guidResGoDic.Remove(tempId); ResourcesManager.Instance.ReleaseResources(resGo, isDestroy); resGo.Reset(); m_resGoClassPool.Recycle(resGo); } else { uint pathCrc = resGo.Crc; if (!m_resGoObjectPoolDic.ContainsKey(pathCrc)) { m_resGoObjectPoolDic.Add(pathCrc, new List <ResourceGameObject>()); } List <ResourceGameObject> tempList = m_resGoObjectPoolDic[pathCrc]; if (tempList.Count < maxRecycleCount || maxRecycleCount < 0) { #if UNITY_EDITOR go.name += "(Recycle)"; #endif if (resGo.IsRecycle == false) { //回收 ResourcesManager.Instance.DecreaseResGoRefCount(resGo); resGo.IsRecycle = true; tempList.Add(resGo); } if (toParent) { go.transform.SetParent(RecycleObjectsTr); } else { go.SetActive(false); } } else { m_guidResGoDic.Remove(tempId); ResourcesManager.Instance.ReleaseResources(resGo, isDestroy); resGo.Reset(); m_resGoClassPool.Recycle(resGo); } } }
private IEnumerator AsyncLoadCoroutine() { long preYieldTime = System.DateTime.Now.Ticks; //上一次返回的时间点 List <AsyncLoadCallBack> callBackList = null; while (true) { bool hadYield = false; for (int i = 0; i < (int)AsyncLoadPriority.Num; i++) //每次循环都是从最高优先级开始的(0) { List <AsyncLoadDataItem> asyncDataItemList = m_asyncLoadItemListArray[i]; if (asyncDataItemList == null || asyncDataItemList.Count <= 0) { continue; } if (m_asyncLoadItemListArray[(int)AsyncLoadPriority.High].Count > 0) { i = (int)AsyncLoadPriority.High; } else if (m_asyncLoadItemListArray[(int)AsyncLoadPriority.Middile].Count > 0) { i = (int)AsyncLoadPriority.Middile; } AsyncLoadDataItem asyncDataItem = asyncDataItemList[0]; asyncDataItemList.Remove(asyncDataItem); Object obj = null; AssetBundleDataItem dataItem = null; #if UNITY_EDITOR if (!GameRoot.m_UseAssetBundleInEditor) { if (asyncDataItem.IsSprite) { obj = LoadABDataItemInEditorMode <Sprite>(asyncDataItem.Path); } else { obj = LoadABDataItemInEditorMode <Object>(asyncDataItem.Path); } //模拟异步加载 yield return(new WaitForSeconds(0.5f)); dataItem = AssetBundleManager.Instance.GetABDataItem(asyncDataItem.Crc); } #endif if (obj == null) { dataItem = AssetBundleManager.Instance.LoadABDataItem(asyncDataItem.Crc); AssetBundleRequest abRequest = null; if (asyncDataItem.IsSprite) { abRequest = dataItem.AB.LoadAssetAsync <Sprite>(dataItem.AssetName); } else { abRequest = dataItem.AB.LoadAssetAsync(dataItem.AssetName); } yield return(abRequest); if (abRequest.isDone) { obj = abRequest.asset; } yield return(obj); preYieldTime = System.DateTime.Now.Ticks; } callBackList = asyncDataItem.CallBackList; //缓存dataitem CacheABDataItem(asyncDataItem.Path, ref dataItem, obj, callBackList.Count); //执行回调列表 for (int j = 0; j < callBackList.Count; j++) { AsyncLoadCallBack callBack = null; callBack = callBackList[j]; if (callBack != null) { //不需要实例化资源的异步加载回调 if (callBack.DealFinish != null) { callBack.DealFinish(asyncDataItem.Path, obj, callBack.Param1, callBack.Param2, callBack.Param3); callBack.DealFinish = null; } //实例化对象异步加载回调 if (callBack.ResGoDealFinish != null && callBack.resGo != null) { //执行这个回调会赋值resGo的abDataItem,(因为在协程里面才是加载dataItem的) ResourceGameObject resGo = callBack.resGo; resGo.ABDataItem = dataItem; callBack.ResGoDealFinish(asyncDataItem.Path, resGo, resGo.Param1, resGo.Param2, resGo.Param3); callBack.ResGoDealFinish = null; resGo = null; } callBack.Reset(); //重置 m_asyncCallBackPool.Recycle(callBack); //回收类对象 } } //清理,回收 asyncDataItem.Reset(); //重置 m_asyncLoadingItemDic.Remove(asyncDataItem.Crc); //从正在加载dic中移除 m_asyncDataItemPool.Recycle(asyncDataItem); //回收类对象 obj = null; callBackList.Clear(); if (System.DateTime.Now.Ticks - preYieldTime > MAXASYNCLOADTIME) { hadYield = true; //等待一帧 yield return(null); preYieldTime = System.DateTime.Now.Ticks; } } if (!hadYield && System.DateTime.Now.Ticks - preYieldTime > MAXASYNCLOADTIME) { preYieldTime = System.DateTime.Now.Ticks; yield return(null); } } }
/// <summary> /// 回收到对象池时减少ABDataItem的引用计数 /// </summary> public int DecreaseResGoRefCount(ResourceGameObject resGo, int count = 1) { return(resGo != null?DecreaseRefCount(resGo.Crc, count) : 0); }