/// <summary> /// 异步加载bundle列表 /// </summary> /// <param name="packInfo">bundle打包信息</param> /// <param name="complete">加载完成回调</param> /// <param name="failure">加载失败回调</param> /// <param name="loading">加载进度回调</param> /// <returns></returns> public IEnumerator LoadAsync(JWObjList <BundlePackInfo> packInfos, BundleLoadedDelegate complete, BundleLoadFailedDelegate failure, BundleLoadingDelegate loading = null) { if (packInfos == null) { JW.Common.Log.LogE("Async loading bundle with null pack info."); yield break; } //JWObjList<BundleRef> bundleRefs = new JWObjList<BundleRef>(); for (int i = 0; i < packInfos.Count; ++i) { BundlePackInfo packInfo = packInfos[i]; if (packInfo != null) { // ab has been loaded BundleRef br = null; if (_bundleDict.TryGetValue(packInfo.Path, out br)) { br.RefCnt++; if (_unloadingBundle.ContainsKey(packInfo.Path)) { _unloadingBundle.Remove(packInfo.Path); } if (loading != null) { loading(packInfo, 1f); } if (complete != null) { complete(br); } continue; } // loading if (_loadingBundle.Contains(packInfo.Path)) { yield return(null); while (_loadingBundle.Contains(packInfo.Path)) { yield return(null); } if (_bundleDict.TryGetValue(packInfo.Path, out br)) { br.RefCnt++; if (complete != null) { complete(br); } } continue; } if (packInfo.HasFlag(EBundleFlag.UnCompress) || packInfo.HasFlag(EBundleFlag.LZ4)) { LoadSync(packInfo); yield break; } //LZMA // 放在加载依赖前,因为加载依赖表示已经开始加载了 _loadingBundle.Add(packInfo.Path); // dependency for (int j = 0; packInfo.Dependencies != null && j < packInfo.Dependencies.Count; j++) { yield return(StartCoroutine(LoadAsync(packInfo.Dependencies[j], null, null))); } // no bundle if (packInfo.IsNoBundle() && !packInfo.Outside) { _loadingBundle.Remove(packInfo.Path); yield break; } // load string path = GetBundleFullPath(packInfo, true); JW.Common.Log.LogD("Async load bundle liat path:{0}", path); UnityWebRequest www = null; www = UnityWebRequest.GetAssetBundle(path); yield return(www.SendWebRequest()); // loading progress if (loading != null) { float progress = 0.0f; while (string.IsNullOrEmpty(www.error) && !www.isDone) { if (www.downloadProgress < 0.00001 && www.downloadProgress > -0.00001) { progress += 0.01f; loading(packInfo, progress); } else { loading(packInfo, www.downloadProgress); } yield return(null); } if (string.IsNullOrEmpty(www.error)) { loading(packInfo, 1f); } } _loadingBundle.Remove(packInfo.Path); // failed if (!string.IsNullOrEmpty(www.error)) { JW.Common.Log.LogE("Async loading bundle {0} failed, error:{1}", packInfo.Path, www.error); if (failure != null) { failure(packInfo, www.error); } www.Dispose(); continue; } AssetBundle ab = DownloadHandlerAssetBundle.GetContent(www); // succeed if (ab != null) { br = new BundleRef(packInfo); br.Bundle = ab; _bundleDict.Add(packInfo.Path, br); if (complete != null) { complete(br); } } www.Dispose(); } } }
/// <summary> /// 批量并发加载bundle /// </summary> /// <param name="bundleList">bundle打包信息列表</param> /// <param name="complete">全部加载完成回调</param> /// <param name="progress">加载进度,0-1</param> /// <returns></returns> public IEnumerator BatchLoadAsync(JWObjList <BundlePackInfo> bundleList, Action complete, BundleBatchLoadingDelegate progress = null, BundleLoadedDelegate loaded = null, BundleLoadFailedDelegate failure = null) { if (bundleList == null || bundleList.Count == 0) { if (progress != null) { progress(1f); } if (complete != null) { complete(); } yield break; } // 并发加载多个bundle JWObjList <string> failedBundles = null; Dictionary <string, float> progressDict = new Dictionary <string, float>(bundleList.Count); // 因为是并发,所以计算进度稍微复杂一些,需要每个bundle的进度收集计算 float step = 1f / bundleList.Count; // 大致平分每个bundle的加载时间 for (int i = 0; i < bundleList.Count; i++) { BundlePackInfo bundleInfo = bundleList[i]; StartCoroutine(LoadAsync(bundleInfo, delegate(BundleRef bundleRef) { // complete one if (bundleRef != null) { // 已加载完成某一个bundle if (loaded != null) { loaded(bundleRef); } if (progressDict.ContainsKey(bundleRef.Path)) { progressDict[bundleRef.Path] = 1f; } else { progressDict.Add(bundleRef.Path, 1f); } } }, delegate(BundlePackInfo packInfo, string error) { if (failedBundles == null) { failedBundles = new JWObjList <string>(); } if (!failedBundles.Contains(packInfo.Path)) { failedBundles.Add(packInfo.Path); } if (failure != null) { failure(packInfo, error); } }, delegate(BundlePackInfo packInfo, float prog) { // 加载进度回调,会有多次 if (progress != null) { // 记录每次每个bundle的进度 if (progressDict.ContainsKey(packInfo.Path)) { progressDict[packInfo.Path] = prog; } else { progressDict.Add(packInfo.Path, prog); } // 计算总进度 float totalProgress = 0; for (int j = 0; j < bundleList.Count; j++) { float eachProg = 0; if (progressDict.TryGetValue(bundleList[j].Path, out eachProg)) { totalProgress += eachProg * step; } } progress(totalProgress); } })); } // 检查是否全部完成 while (true) { bool completed = true; for (int i = 0; i < bundleList.Count; i++) { BundlePackInfo bundleInfo = bundleList[i]; if (_bundleDict.ContainsKey(bundleInfo.Path)) { continue; } if (failedBundles != null && failedBundles.Contains(bundleInfo.Path)) { continue; } completed = false; yield return(null); break; } if (completed) { if (complete != null) { complete(); } yield break; } } }
//异步 #region Load Asynchronize /// <summary> /// 异步加载bundle /// </summary> /// <param name="packInfo">bundle打包信息</param> /// <param name="complete">加载完成回调</param> /// <param name="failure">加载失败回调</param> /// <param name="loading">加载进度回调</param> /// <returns></returns> public IEnumerator LoadAsync(BundlePackInfo packInfo, BundleLoadedDelegate complete, BundleLoadFailedDelegate failure, BundleLoadingDelegate loading = null) { if (packInfo == null) { JW.Common.Log.LogE("Async loading bundle with null pack info."); yield break; } //判断是否已经加载 BundleRef br = null; if (_bundleDict.TryGetValue(packInfo.Path, out br)) { br.RefCnt++; if (_unloadingBundle.ContainsKey(packInfo.Path)) { _unloadingBundle.Remove(packInfo.Path); } if (loading != null) { loading(packInfo, 1f); } if (complete != null) { complete(br); } yield break; } // 正在加载 if (_loadingBundle.Contains(packInfo.Path)) { yield return(null); while (_loadingBundle.Contains(packInfo.Path)) { yield return(null); } if (_bundleDict.TryGetValue(packInfo.Path, out br)) { br.RefCnt++; if (complete != null) { complete(br); } } yield break; } //LoadFormFile 同步加载 if (packInfo.HasFlag(EBundleFlag.UnCompress) || packInfo.HasFlag(EBundleFlag.LZ4)) { LoadSync(packInfo); yield break; } //LZMA _loadingBundle.Add(packInfo.Path); // 依赖 for (int i = 0; packInfo.Dependencies != null && i < packInfo.Dependencies.Count; i++) { yield return(StartCoroutine(LoadAsync(packInfo.Dependencies[i], null, null))); } // 内部含有 if (packInfo.IsNoBundle() && !packInfo.Outside) { _loadingBundle.Remove(packInfo.Path); if (failure != null) { failure(packInfo, ""); } yield break; } { //对于LZMA AssetBundle.LoadFromFileAsync 会占用解压内存 //手册说用UnityWebRequest 可以首次解压 后缓存,但对于本地的包又说用AssetBundle.LoadFromFileAsync string path = GetBundleFullPath(packInfo, false); JW.Common.Log.LogD("Async load bundle path:{0}", path); AssetBundleCreateRequest www = AssetBundle.LoadFromFileAsync(path); float progress = 0.0f; while (!www.isDone) { if (loading != null) { if (www.progress < 0.00001 && www.progress > -0.00001) { progress += 0.01f; loading(packInfo, progress); } else { loading(packInfo, www.progress); } } yield return(null); } _loadingBundle.Remove(packInfo.Path); // failed if (www.assetBundle == null) { JW.Common.Log.LogE("Async loading bundle {0} failed, error:{1}", path, ""); if (failure != null) { failure(packInfo, ""); } www = null; yield break; } if (loading != null) { loading(packInfo, 1f); } // succeed if (www.assetBundle != null) { br = new BundleRef(packInfo); br.Bundle = www.assetBundle; _bundleDict.Add(packInfo.Path, br); if (complete != null) { complete(br); } } www = null; } /*Test2 * { * string path = GetBundleFullPath(packInfo, true); * JW.Common.Log.LogD("Async load bundle use UnityWebRequest path:{0}", path); * UnityWebRequest www = UnityWebRequest.GetAssetBundle(path); * yield return www.SendWebRequest(); * float progress = 0.0f; * while (!www.isDone) * { * if (loading != null) * { * if (www.downloadProgress < 0.00001 && www.downloadProgress > -0.00001) * { * progress += 0.01f; * loading(packInfo, progress); * } * else * { * loading(packInfo, www.downloadProgress); * } * } * yield return null; * } * * _loadingBundle.Remove(packInfo.Path); * // failed * AssetBundle ab = DownloadHandlerAssetBundle.GetContent(www); * if (ab == null) * { * JW.Common.Log.LogE("Async loading bundle use UnityWebRequest {0} failed, error:{1}", path, ""); * if (failure != null) * { * failure(packInfo, ""); * } * www.Dispose(); * www = null; * yield break; * } * * if (loading != null) * { * loading(packInfo, 1f); * } * * // succeed * if (ab != null) * { * br = new BundleRef(packInfo); * br.Bundle = ab; * _bundleDict.Add(packInfo.Path, br); * * if (complete != null) * { * complete(br); * } * } * www.Dispose(); * www = null; * }*/ }