/// <summary> /// 异步下载需要更新的资源 /// </summary> /// <param name="ev">下载完成回调函数</param> /// <returns></returns> IEnumerator AsyncDownloading(ProcessCompleteEvent ev) { mTotalDownloadBytes = 0; mCurrentDownloadIdx = 0; mAlreadyDownloadBytes = 0; foreach (var v in mDownloadingList) { mTotalDownloadBytes += v.m_FileSize; } foreach (var v in mDownloadingList) { string url = mHttpAddress + ResUtils.GetBundleManifestName(Application.platform) + "/" + v.m_Name; UnityEngine.Debug.LogFormat("downloading {0} size {1}", v.m_Name, v.m_FileSize); WWW www = new WWW(url); mWWW = www; yield return(www); if (www.error == null) { string fileName = ResUtils.BundleRootPath + v.m_Name; string dir = fileName.Substring(0, fileName.LastIndexOf('/')); Directory.CreateDirectory(dir); File.WriteAllBytes(fileName, www.bytes); } else { UnityEngine.Debug.LogErrorFormat("downloading {0} error {1}", v.m_Name, www.error); } mAlreadyDownloadBytes += v.m_FileSize; mCurrentDownloadIdx++; } //全部下载成功后,再覆盖写入索引文件 Directory.CreateDirectory(ResUtils.BundleRootPath); if (mNewIndexContent != null) { File.WriteAllText(ResUtils.BundleRootPath + ResUtils.BundleIndexFileName, mNewIndexContent); mNewIndexContent = null; } ev?.Invoke(); yield return(null); }
/// <summary> /// 从服务器得到资源列表并对比出需要更新的包列表 /// </summary> /// <param name="ev">检查完成后回调函数</param> /// <returns></returns> IEnumerator AsyncCheckDownloadingList(ProcessCompleteEvent ev) { //读取本地的idx和apk里的idx文件 Dictionary <string, BundleItem> localBundlesDict = new Dictionary <string, BundleItem>(); string localIndexPath = ResUtils.BundleRootPath + ResUtils.BundleIndexFileName; if (!File.Exists(localIndexPath)) //如果P目录里没有索引文件,去Resources里拷贝一份到P目录 { UnityEngine.Debug.Log("local idx not found, try copy from default"); Directory.CreateDirectory(ResUtils.BundleRootPath); var txt = Resources.Load(ResUtils.BundleIndexFileName.Substring(ResUtils.BundleIndexFileName.IndexOf('.'))) as TextAsset; if (txt != null) { File.WriteAllText(ResUtils.BundleRootPath + ResUtils.BundleIndexFileName, txt.text); } } if (File.Exists(localIndexPath)) { string indexContent = File.ReadAllText(localIndexPath); if (indexContent != null) { IdxFile file = new IdxFile(); List <BundleItem> list = file.Load(indexContent); foreach (var v in list) { localBundlesDict[v.m_Name] = v; } } } else { UnityEngine.Debug.LogWarning("local idx not found"); } //下载网上的idx文件 WWW www = new WWW(mHttpAddress + ResUtils.GetBundleManifestName(Application.platform) + "/" + ResUtils.BundleIndexFileName); yield return(www); if (www.error != null) { UnityEngine.Debug.Log("remote idx read error " + www.error); } mDownloadingList.Clear(); if (www.error == null) { mNewIndexContent = www.text; IdxFile file = new IdxFile(); List <BundleItem> listServer = file.Load(mNewIndexContent); foreach (var v in listServer) { string localHash = null; string netHash = v.m_HashCode; BundleItem localItem = null; if (localBundlesDict.TryGetValue(v.m_Name, out localItem)) { localHash = localItem.m_HashCode; } if (localHash != netHash) { mDownloadingList.Add(v); //网上的资源较新则需要重新下载到本地 } } UnityEngine.Debug.LogFormat("download idx file success! new bundles count {0}, downloading {1}", listServer.Count, mDownloadingList.Count); } else { UnityEngine.Debug.LogFormat("download idx file error! {0}", www.error); } ev?.Invoke(); yield return(null); }
/// <summary> /// 从AB包里加载资源 /// </summary> /// <param name="assetPath">资源路径,例如 subdir/res1.prefab </param> /// <param name="type">资源类型</param> /// <returns>加载好的资源对象</returns> private UnityEngine.Object LoadAssetFromBundle(string assetPath, Type type) { //检查依赖关系是否加载,如果没有则加载 if (mAssetBundleManifest == null) { AssetBundle manifestBundle = AssetBundle.LoadFromFile(ResUtils.BundleRootPath + ResUtils.GetBundleManifestName(Application.platform)); if (manifestBundle == null) { return(null); } mAssetBundleManifest = manifestBundle.LoadAsset("AssetBundleManifest", typeof(AssetBundleManifest)) as AssetBundleManifest; if (mAssetBundleManifest == null) { return(null); } } //获取资源在包内部的名字,这个名字没有路径,但有扩展名,例如 res1.prefab string assetName = assetPath.Substring(assetPath.LastIndexOf("/") + 1).ToLower(); //得到bundle文件的相对路径名,例如 subdir/res1.prefab.unity3d string bundleFileName = assetPath + '.' + ResUtils.BundleExtension; AssetBundleInfo bundleInfo = null; if (mLoadedAssetBundles.TryGetValue(bundleFileName, out bundleInfo)) { bundleInfo.mReferencedCount++; if (!bundleInfo.mAssetBundle.isStreamedSceneAssetBundle) { UnityEngine.Object obj = bundleInfo.mAssetBundle.LoadAsset(assetName, type); return(obj); } else { return(null); //场景包不需要加载资源,返回即可 } } else { LoadDependencies(bundleFileName); bundleInfo = LoadAssetBundleSingle(bundleFileName); if (bundleInfo != null && !bundleInfo.mAssetBundle.isStreamedSceneAssetBundle) { UnityEngine.Object obj = bundleInfo.mAssetBundle.LoadAsset(assetName, type); return(obj); } else { return(null); //场景包不需要加载资源,返回即可 } } }