/// <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> /// 异步资源加载,外部直接调用,(仅仅加载不需要实例化的资源,例如Texture和音频之类的) /// </summary> public void AsyncLoadResource(string path, OnAsyncFinish dealFinish, LoadResPriority priority, bool isSprite = false, uint crc = 0, params object[] paramList) { if (crc == 0) { crc = Crc32.GetCrc32(path); } AssetBundleInfo abInfo = GetCacheAssetBundleInfo(crc); if (abInfo != null) { dealFinish?.Invoke(path, abInfo.m_Obj, paramList); return; } //判断是否在加载中 AsyncLoadResUnit unit = null; //没有找到这个异步加载单位,或者这个异步加载单位是空 if (!m_LoadingAssetDic.TryGetValue(crc, out unit) || unit == null) { unit = m_AsyncLoadResParamPool.Spawn(true); unit.m_Crc = crc; unit.m_Path = path; unit.m_Sprite = isSprite; unit.m_Priority = priority; m_LoadingAssetDic.Add(crc, unit); //添加到正在异步加载的资源dic中 m_loadingAssetList[(int)priority].Add(unit); //按照加载优先级,添加到对应的正在异步加载的资源列表中 } //往回调列表里面添加回调 AsynCallBack callBack = m_AsynCallBackPool.Spawn(true); callBack.m_DealFinish = dealFinish; callBack.m_Params = paramList; //往这个异步加载单位的回调列表中添加一个回调 //可能多个地方加载同一份资源,这样做只加载一次资源, //加载完了后,根据回调列表一次返回这份资源 unit.m_CallBackList.Add(callBack); }
/// <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> /// <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); } } }