/// <summary> /// 写入下载缓存信息,用于断点续传 /// </summary> void SaveDownloadCacheData() { if (CurrentState < emState.UpdateAssetBundle) { return; } if (!Directory.Exists(Common.CACHE_PATH)) { return; } //载入新的Manifest string new_manifest_name = Common.GetCacheFileFullName(Common.MAIN_MANIFEST_FILE_NAME); AssetBundleManifest new_manifest = Common.LoadMainManifestByPath(new_manifest_name); if (new_manifest == null) { return; } //先尝试读取旧的缓存信息,再保存现在已经下载的数据 //PS:由于只有版本完整更新完才会移动Cache目录,且玩家可能多次尝试下载更新,所以必须保留旧的缓存信息 DownloadCache cache = new DownloadCache(); cache.Load(Common.DOWNLOADCACHE_FILE_PATH); if (ab_download_ != null && ab_download_.CompleteDownloads != null && ab_download_.CompleteDownloads.Count > 0) { for (int i = 0; i < ab_download_.CompleteDownloads.Count; ++i) { string assetbundle_name = ab_download_.CompleteDownloads[i]; Hash128 hash_code = new_manifest.GetAssetBundleHash(assetbundle_name); if (hash_code.isValid && !cache.Data.AssetBundles.ContainsKey(assetbundle_name)) { DownloadCacheData.AssetBundle elem = new DownloadCacheData.AssetBundle() { AssetBundleName = assetbundle_name, Hash = hash_code.ToString(), }; Debug.Log(cache.Data.AssetBundles.Count + " - Cache Add:" + assetbundle_name); cache.Data.AssetBundles.Add(assetbundle_name, elem); } } } if (cache.HasData()) { cache.Save(Common.DOWNLOADCACHE_FILE_PATH); } }
/// <summary> /// 比较AssetBundle差异,获得下载列表与删除列表 /// </summary> static void CompareAssetBundleDifference(ref List <string> download_files, ref List <string> delete_files, AssetBundleManifest old_manifest, AssetBundleManifest new_manifest, ResourcesManifest old_resourcesmanifest, ResourcesManifest new_resourcesmanifest) { if (download_files != null) { download_files.Clear(); } if (delete_files != null) { delete_files.Clear(); } if (old_manifest == null) { return; } if (new_manifest == null) { return; } if (new_resourcesmanifest == null) { return; } //采用位标记的方式判断资源 //位标记: 0: 存在旧资源中 1: 存在新资源中 2:本地资源标记 int old_version_bit = 0x1; // 存在旧资源中 int new_version_bit = 0x2; // 存在新资源中 int old_version_native_bit = 0x4; // 旧的本地资源 int new_version_native_bit = 0x8; // 新的本地资源 Dictionary <string, int> temp_dic = new Dictionary <string, int>(); //标记旧资源 string[] all_assetbundle = old_manifest.GetAllAssetBundles(); for (int i = 0; i < all_assetbundle.Length; ++i) { string name = all_assetbundle[i]; _SetDictionaryBit(ref temp_dic, name, old_version_bit); } //标记新资源 string[] new_all_assetbundle = new_manifest.GetAllAssetBundles(); for (int i = 0; i < new_all_assetbundle.Length; ++i) { string name = new_all_assetbundle[i]; _SetDictionaryBit(ref temp_dic, name, new_version_bit); } //标记旧的本地资源 if (old_resourcesmanifest.Data != null && old_resourcesmanifest.Data.AssetBundles != null) { var resource_manifest_itr = old_resourcesmanifest.Data.AssetBundles.GetEnumerator(); while (resource_manifest_itr.MoveNext()) { if (resource_manifest_itr.Current.Value.IsNative) { string name = resource_manifest_itr.Current.Value.AssetBundleName; _SetDictionaryBit(ref temp_dic, name, old_version_native_bit); } } } //标记新的本地资源 if (new_resourcesmanifest.Data != null && new_resourcesmanifest.Data.AssetBundles != null) { var resource_manifest_itr = new_resourcesmanifest.Data.AssetBundles.GetEnumerator(); while (resource_manifest_itr.MoveNext()) { if (resource_manifest_itr.Current.Value.IsNative) { string name = resource_manifest_itr.Current.Value.AssetBundleName; _SetDictionaryBit(ref temp_dic, name, new_version_native_bit); } } } //获得对应需操作的文件名, 优先级: both > add > delete //both: 第0位与第1位都被标记的 //delete: 仅第0位被标记的 //add: 第2位未标记,且第3位被标记的 int both_bit = old_version_bit | new_version_bit; // 二个版本资源都存在 List <string> add_files = new List <string>(); List <string> both_files = new List <string>(); var itr = temp_dic.GetEnumerator(); while (itr.MoveNext()) { string name = itr.Current.Key; int mask = itr.Current.Value; if ((mask & new_version_native_bit) == new_version_native_bit && (mask & old_version_native_bit) == 0) { add_files.Add(name); } else if ((mask & both_bit) == both_bit) { both_files.Add(name); } else if ((mask & old_version_bit) == old_version_bit) { delete_files.Add(name); } } itr.Dispose(); //载入下载缓存数据 DownloadCache download_cache = new DownloadCache(); download_cache.Load(Common.DOWNLOADCACHE_FILE_PATH); if (!download_cache.HasData()) { download_cache = null; } //记录需下载的文件 { //加入新增的文件 download_files.AddRange(add_files); //比较所有同时存在的文件,判断哪些需要更新 for (int i = 0; i < both_files.Count; ++i) { string name = both_files[i]; string full_name = Common.GetFileFullName(name); if (File.Exists(full_name)) { //判断哈希值是否相等 string old_hash = old_manifest.GetAssetBundleHash(name).ToString(); string new_hash = new_manifest.GetAssetBundleHash(name).ToString(); if (old_hash.CompareTo(new_hash) == 0) { continue; } download_files.Add(name); } } //过滤缓存中已下载的文件 if (download_cache != null) { var cache_itr = download_cache.Data.AssetBundles.GetEnumerator(); while (cache_itr.MoveNext()) { DownloadCacheData.AssetBundle elem = cache_itr.Current.Value; string name = elem.AssetBundleName; string full_name = Common.GetFileFullName(name); if (File.Exists(full_name)) { string cache_hash = elem.Hash; string new_hash = new_manifest.GetAssetBundleHash(name).ToString(); if (!string.IsNullOrEmpty(cache_hash) && cache_hash.CompareTo(new_hash) == 0) { download_files.Remove(name); } } } } } }
/// <summary> /// 更新AssetBundle /// </summary> IEnumerator UpdatingUpdateAssetBundle() { if (ErrorCode != emErrorCode.None) { yield break; } UpdateCompleteValue(0f, 0f); //载入新的ResourcesManifest ResourcesManifest old_resource_manifest = AssetBundleManager.Instance.ResManifest; string file = Common.UPDATER_CACHE_PATH + "/" + Common.RESOURCES_MANIFEST_FILE_NAME; ResourcesManifest new_resources_manifest = Common.LoadResourcesManifestByPath(file); if (new_resources_manifest == null) { Error(emErrorCode.LoadNewResourcesManiFestFailed , "Can't load new verion ResourcesManifest!"); yield break; } //载入MainManifest AssetBundleManifest manifest = AssetBundleManager.Instance.MainManifest; file = Common.UPDATER_CACHE_PATH + "/" + Common.MAIN_MANIFEST_FILE_NAME; AssetBundleManifest new_manifest = Common.LoadMainManifestByPath(file); if (new_manifest == null) { Error(emErrorCode.LoadNewMainManifestFailed , "Can't find new version MainManifest!"); yield break; } //获取需下载的资源列表与删除的资源的列表 List <string> download_files = new List <string>(); List <string> delete_files = new List <string>(); ComparisonUtils.CompareAndCalcDifferenceFiles(ref download_files, ref delete_files , manifest, new_manifest , old_resource_manifest, new_resources_manifest , ComparisonUtils.emCompareMode.All); // 进度控制 float totalProgress = delete_files.Count + download_files.Count; float currentProgress = 0; //载入下载缓存数据, 过滤缓存中已下载的文件 DownloadCache download_cache = new DownloadCache(); download_cache.Load(Common.DOWNLOADCACHE_FILE_PATH); if (!download_cache.HasData()) { download_cache = null; } if (download_cache != null) { var cache_itr = download_cache.Data.AssetBundles.GetEnumerator(); while (cache_itr.MoveNext()) { DownloadCacheData.AssetBundle elem = cache_itr.Current.Value; string name = elem.AssetBundleName; string full_name = Common.GetFileFullName(name); if (File.Exists(full_name)) { string cache_hash = elem.Hash; string new_hash = new_manifest.GetAssetBundleHash(name).ToString(); if (!string.IsNullOrEmpty(cache_hash) && cache_hash.CompareTo(new_hash) == 0) { download_files.Remove(name); ++currentProgress; UpdateCompleteValue(currentProgress, totalProgress); yield return(null); } } } } //删除已废弃的文件 if (delete_files.Count > 0) { for (int i = 0; i < delete_files.Count; ++i) { string full_name = Common.GetFileFullName(delete_files[i]); if (File.Exists(full_name)) { File.Delete(full_name); ++currentProgress; UpdateCompleteValue(currentProgress, totalProgress); yield return(null); } } } //更新所有需下载的资源 ab_download_ = new AssetBundleDownloader(current_url_); ab_download_.Start(Common.PATH, download_files, new_resources_manifest); while (!ab_download_.IsDone) { UpdateCompleteValue(currentProgress + ab_download_.CompleteDownloadList.Count, totalProgress); yield return(null); } if (ab_download_.IsFailed) { Error(ab_download_.ErrorCode); yield break; } }