public void Reset() { m_DealFinish = null; m_DealResObjFinish = null; m_Params = null; m_ResObj = null; }
/// <summary> /// 清除某个资源在对象池中所有的对象 /// </summary> /// <param name="crc"></param> public void ClearPoolObject(uint crc) { List <ResourceObj> st = null; if (!m_ObjectPoolDic.TryGetValue(crc, out st) || st == null) { return; } for (int i = st.Count - 1; i >= 0; i--) { ResourceObj resObj = st[i]; if (resObj.m_bClear) { st.Remove(resObj); int tempID = resObj.m_CloneObj.GetInstanceID(); GameObject.Destroy(resObj.m_CloneObj); resObj.Reset(); m_ResObjDic.Remove(tempID); m_ResObjClassPool.Recycle(resObj); } } if (st.Count == 0) { m_ObjectPoolDic.Remove(crc); } }
/// <summary> /// 取消异步加载资源 /// </summary> /// <returns></returns> public bool CancleLoad(ResourceObj res) { AsyncLoadResUnit unit = null; //这俩个条件主要来判断该资源还没有进入到异步加载流程 //多个人请求同一份资源,要多个人都取消才能取消这个异步加载单位 //其中一个人取消异步加载,只是把应该给他的回调取消掉 if (m_LoadingAssetDic.TryGetValue(res.m_Crc, out unit) && m_loadingAssetList[(int)unit.m_Priority].Contains(unit)) { for (int i = unit.m_CallBackList.Count - 1; i >= 0; i--) { //取消对应的回调列表 AsynCallBack tempCallBack = unit.m_CallBackList[i]; if (tempCallBack != null && res == tempCallBack.m_ResObj) { tempCallBack.Reset(); m_AsynCallBackPool.Recycle(tempCallBack); unit.m_CallBackList.Remove(tempCallBack); } } //异步加载单位的回调列表为0,表示所有人都取消了这个资源加载,回收他 if (unit.m_CallBackList.Count <= 0) { unit.Reset(); m_loadingAssetList[(int)unit.m_Priority].Remove(unit); m_AsyncLoadResParamPool.Recycle(unit); m_LoadingAssetDic.Remove(res.m_Crc); return(true); } } return(false); }
/// <summary> /// 根据ResourceObj 卸载资源 /// </summary> /// <param name="resObj"></param> /// <param name="destoryObj"></param> /// <returns></returns> public bool ReleaseResource(ResourceObj resObj, bool destoryObj = false) { if (resObj == null) { return(false); } uint crc = resObj.m_Crc; AssetBundleInfo abInfo = null; if (!AssetDic.TryGetValue(resObj.m_Crc, out abInfo) || null == abInfo) { Debug.LogError("该路径:" + resObj.m_CloneObj.name + " 的资源不存在!"); } GameObject.Destroy(resObj.m_CloneObj); abInfo.RefCount--; DestoryResouceItem(abInfo, destoryObj); return(true); //return ReleaseResource(resourceObj.m_AssetBundleInfo.m_Obj, destoryObj); }
/// <summary> /// 从对象池取出一个对象 /// </summary> /// <param name="crc"></param> /// <returns></returns> protected ResourceObj GetObjectFromPool(uint crc) { List <ResourceObj> st = null; if (m_ObjectPoolDic.TryGetValue(crc, out st) && st != null && st.Count != 0) { //增加引用计数 ResourceManager.Instance.IncreaseResourceRef(crc); ResourceObj resObj = st[0]; st.RemoveAt(0); GameObject obj = resObj.m_CloneObj; if (!System.Object.ReferenceEquals(obj, null)) { //还原离线数据 if (!System.Object.ReferenceEquals(resObj.m_offlineData, null)) { resObj.m_offlineData.ResetProp(); } resObj.m_Already = false; #if UNITY_EDITOR if (obj.name.EndsWith("(Recycle)")) { obj.name = obj.name.Replace("(Recycle)", ""); } #endif } return(resObj); } return(null); }
/// <summary> /// 清空对象池 /// </summary> public void ClearCache() { List <uint> tempList = new List <uint>(); foreach (uint key in m_ObjectPoolDic.Keys) { List <ResourceObj> st = m_ObjectPoolDic[key]; for (int i = st.Count - 1; i >= 0; i--) { ResourceObj resObj = st[i]; if (!System.Object.ReferenceEquals(resObj.m_CloneObj, null) && resObj.m_bClear) { GameObject.Destroy(resObj.m_CloneObj); m_ResObjDic.Remove(resObj.m_CloneObj.GetInstanceID()); resObj.Reset(); m_ResObjClassPool.Recycle(resObj); st.Remove(resObj); } } if (st.Count <= 0) { tempList.Add(key); } } for (int i = 0; i < tempList.Count; i++) { if (m_ObjectPoolDic.ContainsKey(tempList[i])) { m_ObjectPoolDic.Remove(tempList[i]); } } tempList.Clear(); }
/// <summary> /// 取消异步加载 /// </summary> /// <param name="guid"></param> public void CancleLoad(long guid) { ResourceObj resObj = null; //根据GUID,找到正在异步加载的资源,并且该资源没有在加载中,回调列表数量是0 if (m_AsyncResObjs.TryGetValue(guid, out resObj) && ResourceManager.Instance.CancleLoad(resObj)) { m_AsyncResObjs.Remove(guid); resObj.Reset(); m_ResObjClassPool.Recycle(resObj); } }
/// <summary> /// 根据实例化对象直接获取离线数据 /// </summary> /// <returns></returns> public OfflineData FindOfflineData(GameObject obj) { OfflineData data = null; ResourceObj resObj = null; m_ResObjDic.TryGetValue(obj.GetInstanceID(), out resObj); if (resObj != null) { data = resObj.m_offlineData; } return(data); }
/// <summary> /// 异步加载 /// </summary> /// <param name="path"></param> /// <param name="fealFinish"></param> /// <param name="priority"></param> /// <param name="setSceneObj"></param> /// <param name="param1"></param> /// <param name="param2"></param> /// <param name="param3"></param> /// <param name="bClear"></param> public long InstantiateObjectAsync(string path, OnAsyncFinish dealFinish, LoadResPriority priority, bool setSceneObj = false, bool bClear = true, params object[] paramList) { if (string.IsNullOrEmpty(path)) { return(0); } uint crc = Crc32.GetCrc32(path); //从缓存池获取 ResourceObj resObj = GetObjectFromPool(crc); //从缓存中拿到了,直接返回 if (resObj != null) { if (setSceneObj) { resObj.m_CloneObj.transform.SetParent(SceneTrs, false); } if (dealFinish != null) { dealFinish(path, resObj.m_CloneObj, paramList); } return(resObj.m_Guid); } //异步加载的GUID long guid = ResourceManager.Instance.CreateGuid(); //缓存中没有,异步加载 resObj = m_ResObjClassPool.Spawn(true); //new一个对象 resObj.m_Crc = crc; resObj.m_SetSceneParent = setSceneObj; resObj.m_bClear = bClear; resObj.m_DealFinish = dealFinish; resObj.m_Params = paramList; //调用ResourceManager的异步加载接口 ResourceManager.Instance.AsyncLoadResource(path, resObj, OnLoadResObjFinish, priority); return(guid); }
/// <summary> /// 实例化资源加载完毕的回调 /// </summary> /// <param name="path">路径</param> /// <param name="resObj">中间类</param> /// <param name="param1">参数1</param> /// <param name="param2">参数2</param> /// <param name="param3">参数3</param> void OnLoadResObjFinish(string path, ResourceObj resObj, params object[] paramList) { if (resObj == null) { return; } if (resObj.m_AssetBundleInfo.m_Obj == null) { #if UNITY_EDITOR Debug.LogError("异步资源加载的资源为空:" + path); #endif } else { //给ResourceObj的实例化对象赋值 resObj.m_CloneObj = GameObject.Instantiate(resObj.m_AssetBundleInfo.m_Obj) as GameObject; resObj.m_offlineData = resObj.m_CloneObj.GetComponent <OfflineData>(); } //加载完成,就从正在加载的异步中移除 if (m_AsyncResObjs.ContainsKey(resObj.m_Guid)) { m_AsyncResObjs.Remove(resObj.m_Guid); } if (resObj.m_CloneObj != null && resObj.m_SetSceneParent) { resObj.m_CloneObj.transform.SetParent(SceneTrs, false); } if (resObj.m_DealFinish != null) { int tempID = resObj.m_CloneObj.GetInstanceID(); if (!m_ResObjDic.ContainsKey(tempID)) { m_ResObjDic.Add(tempID, resObj); } resObj.m_DealFinish(path, resObj.m_CloneObj, resObj.m_Params); } }
/// <summary> /// 异步资源加载,针对ObjectManager的,(需要实例化对象的异步加载) /// </summary> public void AsyncLoadResource(string path, ResourceObj resObj, OnAsyncResObjFinish dealFinish, LoadResPriority priority, uint crc = 0, params object[] paramList) { AssetBundleInfo abInfo = GetCacheAssetBundleInfo(resObj.m_Crc); if (abInfo != null) { resObj.m_AssetBundleInfo = abInfo; if (dealFinish != null) { dealFinish(path, resObj, paramList); } return; } //判断是否在加载中 AsyncLoadResUnit unit = null; //没有找到这个异步加载单位,或者这个异步加载单位是空 if (!m_LoadingAssetDic.TryGetValue(resObj.m_Crc, out unit) || unit == null) { unit = m_AsyncLoadResParamPool.Spawn(true); unit.m_Crc = resObj.m_Crc; unit.m_Path = path; unit.m_Priority = priority; m_LoadingAssetDic.Add(resObj.m_Crc, unit); //添加到正在异步加载的资源dic中 m_loadingAssetList[(int)priority].Add(unit); //按照加载优先级,添加到对应的正在异步加载的资源列表中 } //往回调列表里面添加回调 AsynCallBack callBack = m_AsynCallBackPool.Spawn(true); callBack.m_Params = paramList; callBack.m_DealResObjFinish = dealFinish; callBack.m_ResObj = resObj; //往这个异步加载单位的回调列表中添加一个回调 //可能多个地方加载同一份资源,这样做只加载一次资源, //加载完了后,根据回调列表依次返回这份资源 unit.m_CallBackList.Add(callBack); }
/// <summary> /// 同步加载 /// </summary> /// <param name="path"></param> /// <param name="setSceneObj">是否存到</param> /// <param name="bClear">跳场景是否清空</param> /// <returns></returns> public GameObject InstantiateObject(string path, bool setSceneObj = false, bool bClear = true) { uint crc = Crc32.GetCrc32(path); //从缓存池获取 ResourceObj resObj = GetObjectFromPool(crc); if (resObj == null) { resObj = m_ResObjClassPool.Spawn(true); resObj.m_Crc = crc; resObj.m_bClear = bClear; //ResourceManager提供加载方法 //给resObj.m_AssetBundleInfo 赋值 //给resObj.m_AssetBundleInfo.m_Obj赋值 resObj = ResourceManager.Instance.LoadResource(path, resObj); if (resObj.m_AssetBundleInfo.m_Obj != null) { resObj.m_CloneObj = GameObject.Instantiate(resObj.m_AssetBundleInfo.m_Obj) as GameObject; resObj.m_offlineData = resObj.m_CloneObj.GetComponent <OfflineData>(); } } //setParent会造成性能消耗,所以加个布尔值控制下 if (setSceneObj) { resObj.m_CloneObj.transform.SetParent(SceneTrs, false); } int tempID = resObj.m_CloneObj.GetInstanceID(); if (!m_ResObjDic.ContainsKey(tempID)) { m_ResObjDic.Add(tempID, resObj); } return(resObj.m_CloneObj); }
/// <summary> /// 异步加载 /// </summary> /// <returns></returns> IEnumerator AsyncLoadCor() { List <AsynCallBack> callBackList = null; while (true) { bool haveYield = false; //是否已经等了一帧了 //上次yield的时间 long lastYiledTime = System.DateTime.Now.Ticks; //遍历优先级列表,从0开始,0表示最高 for (int i = 0; i < (int)LoadResPriority.RES_NUM; i++) { //每次循环,只要高级列表有东西,就一直加载高级列表资源,直到加载完毕 if (m_loadingAssetList[(int)LoadResPriority.RES_HIGHT].Count > 0) { i = (int)LoadResPriority.RES_HIGHT; } else if (m_loadingAssetList[(int)LoadResPriority.RES_MIDDLE].Count > 0) { i = (int)LoadResPriority.RES_MIDDLE; } List <AsyncLoadResUnit> loadingList = m_loadingAssetList[i]; if (loadingList.Count <= 0) { continue; } AsyncLoadResUnit loadintItem = loadingList[0]; loadingList.RemoveAt(0); callBackList = loadintItem.m_CallBackList; Object obj = null; AssetBundleInfo abInfo = null; #if UNITY_EDITOR if (!m_LoadFromAssetBundle) { if (loadintItem.m_Sprite) //判断是否是Sprite,因为Unity Object不能转换成Sprite { obj = LoadAssetByEditor <Sprite>(loadintItem.m_Path); } else { obj = LoadAssetByEditor <Object>(loadintItem.m_Path); } //编辑器下模拟异步加载,等0.1f yield return(new WaitForSeconds(0.1f)); abInfo = AssetBundleManager.Instance.FindAssetBundleInfo(loadintItem.m_Crc); if (abInfo == null) { abInfo = new AssetBundleInfo(); abInfo.m_Crc = loadintItem.m_Crc; } } #endif if (obj == null) { abInfo = AssetBundleManager.Instance.LoadAssetBundleInfoAsync(loadintItem.m_Crc); yield return(abInfo); if (abInfo.isDone) { if (abInfo != null && abInfo.m_AssetBundle != null) { AssetBundleRequest abRequest = null; if (loadintItem.m_Sprite) //判断是否是Sprite,因为Unity Object不能转换成Sprite { abRequest = abInfo.m_AssetBundle.LoadAssetAsync <Sprite>(abInfo.m_AssetName); } else { abRequest = abInfo.m_AssetBundle.LoadAssetAsync(abInfo.m_AssetName); } yield return(abRequest); if (abRequest.isDone) { obj = abRequest.asset; } lastYiledTime = System.DateTime.Now.Ticks; } } } CacheAssetBundleInfo(loadintItem.m_Path, ref abInfo, loadintItem.m_Crc, obj, callBackList.Count); //处理回调 for (int j = 0; j < callBackList.Count; j++) { AsynCallBack callBack = callBackList[j]; //实例化对象的回调 if (callBack != null && callBack.m_DealResObjFinish != null && callBack.m_ResObj != null) { ResourceObj tempResObj = callBack.m_ResObj; tempResObj.m_AssetBundleInfo = abInfo; callBack.m_DealResObjFinish(loadintItem.m_Path, tempResObj, callBack.m_Params); callBack.m_DealResObjFinish = null; tempResObj = null; } //非实例化对象的回调 if (callBack != null && callBack.m_DealFinish != null) { callBack.m_DealFinish(loadintItem.m_Path, obj, callBack.m_Params); callBack.m_DealFinish = null; } callBack.Reset(); //还原回调,并且回收 m_AsynCallBackPool.Recycle(callBack); } obj = null; callBackList.Clear(); m_LoadingAssetDic.Remove(loadintItem.m_Crc); loadintItem.Reset(); m_AsyncLoadResParamPool.Recycle(loadintItem); //加载一个资源时间过长,等一帧 if (System.DateTime.Now.Ticks - lastYiledTime > MAXLOADRESTIME) { yield return(null); lastYiledTime = System.DateTime.Now.Ticks; haveYield = true; } } //内存循环加载很快,没有等一帧,但是加载整个优先级列表时间过长,等一帧 if (!haveYield || System.DateTime.Now.Ticks - lastYiledTime > MAXLOADRESTIME) { lastYiledTime = System.DateTime.Now.Ticks; yield return(null); } } }
/// <summary> /// 根据Resobj减少引用计数 /// </summary> /// <returns></returns> public int DecreaseResourceRef(ResourceObj resObj, int count = 1) { return(resObj != null?DecreaseResourceRef(resObj.m_Crc, count) : 0); }
/// <summary> /// 该对象是否是ObjectManager创建的 /// </summary> /// <returns></returns> public bool IsObjectManagerCreate(GameObject obj) { ResourceObj resObj = m_ResObjDic[obj.GetInstanceID()]; return(resObj == null ? false : true); }
/// <summary> /// 同步加载资源,针对给ObjectManager的接口 /// 给ResourceObj.m_AssetBundleInfo赋值用的 /// </summary> /// <param name="path"></param> /// <param name="resObj">传入的resourceObj,</param> /// <returns></returns> public ResourceObj LoadResource(string path, ResourceObj resObj) { if (resObj == null) { return(null); } //获取crc uint crc = resObj.m_Crc == 0 ? Crc32.GetCrc32(path) : resObj.m_Crc; //根据crc从缓存中获取 AssetBundle资源块信息 AssetBundleInfo abInfo = GetCacheAssetBundleInfo(crc); if (abInfo != null) { resObj.m_AssetBundleInfo = abInfo; return(resObj); } Object obj = null; #if UNITY_EDITOR if (!m_LoadFromAssetBundle) { abInfo = AssetBundleManager.Instance.FindAssetBundleInfo(crc); if (abInfo != null && abInfo.m_Obj != null) { obj = abInfo.m_Obj; } else { if (abInfo == null) { abInfo = new AssetBundleInfo(); abInfo.m_Crc = crc; } obj = LoadAssetByEditor <Object>(path); } } #endif //缓存中没有AssetBundle资源块信息,加载它 if (obj == null) { abInfo = AssetBundleManager.Instance.LoadAssetBundleInfo(crc); if (abInfo != null && abInfo.m_AssetBundle != null) { if (abInfo.m_Obj != null) { obj = abInfo.m_Obj; } else { obj = abInfo.m_AssetBundle.LoadAsset <Object>(abInfo.m_AssetName); } } } //将加载的资源放入缓存中 CacheAssetBundleInfo(path, ref abInfo, crc, obj); resObj.m_AssetBundleInfo = abInfo; abInfo.m_Clear = resObj.m_bClear; return(resObj); }
/// <summary> /// 回收资源 /// </summary> /// <param name="obj"></param> /// <param name="maxCacheCount"></param> /// <param name="destoryCache"></param> /// <param name="recycleParent">是否放回回收节点</param> public void ReleaseObject(GameObject obj, int maxCacheCount = -1, bool destoryCache = false, bool recycleParent = true) { if (obj == null) { return; } ResourceObj resObj = null; int temID = obj.GetInstanceID(); if (!m_ResObjDic.TryGetValue(temID, out resObj)) { Debug.Log(obj.name + "对象不是ObjectManager创建的!"); return; } if (resObj == null) { Debug.LogError("缓存的ResourceObj为空"); } if (resObj.m_Already) { Debug.LogError("该对象已经放回对象池了,检查自己是否清空引用"); return; } #if UNITY_EDITOR obj.name += "(Recycle)"; #endif List <ResourceObj> st = null; //不缓存 if (maxCacheCount == 0) { m_ResObjDic.Remove(temID); ResourceManager.Instance.ReleaseResource(resObj, destoryCache); resObj.Reset(); m_ResObjClassPool.Recycle(resObj); } else { //回收到对象池 if (!m_ObjectPoolDic.TryGetValue(resObj.m_Crc, out st) || st == null) { st = new List <ResourceObj>(); m_ObjectPoolDic.Add(resObj.m_Crc, st); } if (resObj.m_CloneObj) { if (recycleParent) //放到资源回收池节点下 { resObj.m_CloneObj.transform.SetParent(RecyclePoolTrs); } else { resObj.m_CloneObj.SetActive(false); } } //不限制最大缓存数量,或者当前缓存数量小于最大缓存数量 if (maxCacheCount < 0 || st.Count < maxCacheCount) { st.Add(resObj); resObj.m_Already = true; //ResourceManager做一个引用计数 ResourceManager.Instance.DecreaseResourceRef(resObj); } else { m_ResObjDic.Remove(temID); ResourceManager.Instance.ReleaseResource(resObj, destoryCache); resObj.Reset(); m_ResObjClassPool.Recycle(resObj); } } }