public static bool GenPatchPackages(string oldResDir, string newResDir) { if (!Directory.Exists(oldResDir) || !Directory.Exists(newResDir)) { return(false); } var oldResVer = GetResVersion(oldResDir); var newResVer = GetResVersion(newResDir); if (oldResVer == null || newResVer == null) { Debug.LogError("资源版本信息加载失败"); return(false); } if (oldResVer > newResVer) { Debug.LogErrorFormat("oldResVer > newResVer:{0} {1}", oldResVer, newResVer); return(false); } else if (oldResVer == newResVer) { //最新版本资源,无需生成补丁包 GenLastestPatchInfo(newResVer); return(true); } string platformName = ResManager.GetBuildPlatformName(); var oldManifest = LoadAssetBundleManifest(oldResDir + "/" + platformName); var newManifest = LoadAssetBundleManifest(newResDir + "/" + platformName); var oldBundleNames = oldManifest.GetAllAssetBundles(); var newBundleNames = newManifest.GetAllAssetBundles(); var allNameSet = new HashSet <string>(oldBundleNames); allNameSet.UnionWith(newBundleNames); var patchedNames = new List <string>(); var sb = new StringBuilder(); int index = 0; foreach (var bundleName in allNameSet) { string oldResPath = oldResDir + "/" + bundleName; string newResPath = newResDir + "/" + bundleName; bool oldResExists = File.Exists(oldResPath); bool newResExists = File.Exists(newResPath); if (oldResExists && newResExists) { //新旧版本都存在的,读取Bundle的Hash和CRC判断 var oldHash = oldManifest.GetAssetBundleHash(bundleName); var newHash = newManifest.GetAssetBundleHash(bundleName); if (oldHash != newHash) { patchedNames.Add(bundleName); sb.AppendFormat("[Patched] 新旧Hash值不一致:{0}\n{1}\n{2}\n\n", bundleName, oldHash, newHash); } else { uint oldCRC; uint newCRC; BuildPipeline.GetCRCForAssetBundle(oldResPath, out oldCRC); BuildPipeline.GetCRCForAssetBundle(newResPath, out newCRC); if (oldCRC != newCRC) { patchedNames.Add(bundleName); sb.AppendFormat("[Patched] 新旧CRC值不一致:{0}\n{1}\n{2}\n\n", bundleName, oldCRC, newCRC); } else { sb.AppendFormat("[ignored] 资源未变更:{0}\n{1}\n{2}\n\n", bundleName, newHash, newCRC); } } } else if (!oldResExists && newResExists) { patchedNames.Add(bundleName); sb.AppendFormat("[Patched] 新增版本资源:{0}\n\n", bundleName); } else if (oldResExists) { sb.AppendFormat("[ignored] 新版本资源被移除或者BundleName变更:{0}\n\n", bundleName); } else { throw new Exception(string.Format("[Error] Backup目录文件被异常删除:{0}\n\n", newResPath)); } index++; EditorUtility.DisplayProgressBar("对比Bundle包版本信息", String.Format(" {0} / {1} ", index, allNameSet.Count), index / (float)allNameSet.Count); } Debug.Log(sb); if (patchedNames.Count > 0) { string patchDir = string.Format("{0}/patch_{1}_{2}", PatchExportPath, oldResVer, newResVer); EditorUtility.DisplayProgressBar("生成补丁包中", patchDir, 0); if (Directory.Exists(patchDir)) { Directory.Delete(patchDir, true); } //AssetBundleManifest也需要拷贝 Dictionary <string, string> fileHash = new Dictionary <string, string>(); patchedNames.Add(ResManager.GetBuildPlatformName()); foreach (var patchedName in patchedNames) { string patchFile = patchDir + "/" + patchedName; CopyFile(newResDir + "/" + patchedName, patchFile); fileHash[patchedName] = SHA256Hashing.HashFile(patchFile); } string zipFile = patchDir + ".zip"; ZipTool.CompressFolder(zipFile, patchDir); string zipHash = MD5Hashing.HashFile(zipFile); long fileSize = new FileInfo(zipFile).Length; string finalZipFile = string.Format("{0}-{1}.zip", patchDir, zipHash); if (File.Exists(finalZipFile)) { File.Delete(finalZipFile); } File.Move(zipFile, finalZipFile); var patchInfo = new PatchInfo { version = oldResVer.ToString(), nextVer = newResVer.ToString(), hash = zipHash, fileSize = fileSize, fileName = Path.GetFileName(finalZipFile), fileHash = fileHash, }; string jsonPath = string.Format("{0}/{1}_{2}.json", PatchExportPath, ResourceModuleConfig.PatchInfoPrefix, oldResVer); FileExt.SaveJsonObj(patchInfo, jsonPath, false, true); Directory.Delete(patchDir, true); Debug.Log("Build Patch Package:" + finalZipFile); } else { Debug.Log("Build Patch Package Skip!!!"); } EditorUtility.ClearProgressBar(); return(true); }