/// <summary> /// Gens the patch files. /// </summary> /// <returns>The patch files.</returns> /// <param name="patchPatch">Patch patch.</param> /// <param name="versionItemSize">Version item size.</param> /// <param name="abPatchDic">Ab patch dic.</param> private static Dictionary <string, string> GenPatchFiles(string patchPath, string abPath, Dictionary <string, List <object> > versionItemInfo, ref Dictionary <string, string> abPatchDic) { Dictionary <string, string> patchVersionDic = new Dictionary <string, string>(); List <string> filterAB = new List <string>(); foreach (KeyValuePair <string, List <string> > item in AssetBundleNameTools.patchAbDict) { filterAB.Clear(); string md5Str = string.Empty; foreach (string reg in item.Value) { List <string> bundles = versionItemInfo.Keys.Where(bundle => (Regex.IsMatch(bundle, reg))).ToList <string>(); if (bundles.Count == 0) { NIDebug.LogError("生成patch时 {0} 筛选出来的文件个数为0,请检查!", reg); continue; } // 对文件按文件名称进行排序 bundles.Sort(delegate(string b1, string b2) { return(b1.CompareTo(b2)); }); foreach (string bundle in bundles) { filterAB.Add(string.Format("{0}{1}", abPath, bundle)); md5Str += versionItemInfo[bundle][0]; if (abPatchDic.ContainsKey(bundle)) { NIDebug.LogError(string.Format("{0}重复放在了{1}和{2}中,请检查!", bundle, abPatchDic[bundle], item.Key)); continue; } abPatchDic.Add(bundle, item.Key); } } string md5 = NIEditorUtility.GetStrMD5(md5Str); NIEditorUtility.Zip(filterAB.ToArray(), string.Format("{0}{1}_{2}.zip", patchPath, item.Key, md5)); patchVersionDic.Add(item.Key, md5); } return(patchVersionDic); }
/// <summary> /// 发布资源 /// </summary> private static void DoBuildPublish(BuildTarget target, string resVersion, bool isNewAssets, string channel) { string rootPath = GetABRootPath(target, channel); string publishPath = string.Format("{0}/PublishAssetBundles/", rootPath); string abPath = string.Format("{0}/AssetBundles/", rootPath); string patchPath = string.Format("{0}/PatchAssetBundles/", rootPath); string encryptPath = string.Format("{0}/EncryptAssetBundles/", rootPath); // 如果需要重新打包资源则删除原来的版本文件 if (isNewAssets) { FileMgr.DeleteDirectory(abPath); } // ab路径是否存在,不存在则创建一个 DirectoryInfo abInfo = new DirectoryInfo(abPath); if (!abInfo.Exists) { abInfo.Create(); } // 确保目录存在 FileMgr.DeleteDirectory(encryptPath); FileMgr.CreateDirectory(encryptPath); FileMgr.DeleteDirectory(publishPath); FileMgr.CreateDirectory(publishPath); FileMgr.DeleteDirectory(patchPath); FileMgr.CreateDirectory(patchPath); BuildAssetBundleOptions opt = BuildAssetBundleOptions.DeterministicAssetBundle | // 保证同样的资源多次打包出的assetbundle相同 BuildAssetBundleOptions.UncompressedAssetBundle; // 不压缩资源,我们会压缩,然后在目标平台解压缩,最后使用的是没有压缩的资源,保证资源快速加载 // AssetBundle打包,Unity5.x之后都是用这个方法打包,而且还会自动生成依赖关系 AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(abPath, opt, target); // 载入旧版本树 CsvFile oldVersionCsv = LoadVersion(abPath); // 生成资源映射表 GenResourceDictFile(abPath, manifest); //// 加密ab资源包 DoEncryptAssetBundle(encryptPath, abPath, manifest); // 收集需要发布的ab资源包 Dictionary <string, string> newABVersion = DoCollectNewABVersion(encryptPath, manifest); // 资源大小映射表 Dictionary <string, List <object> > versionItemInfo = new Dictionary <string, List <object> >(); // 是否需要更新标识 bool isABChanged = false; byte[] unzipBuf; byte[] buf; // 发布资源 foreach (string abName in newABVersion.Keys) { // 获取旧版本信息 CsvRow data = oldVersionCsv.FindByKey(abName); if ((data != null) && string.Equals(data.Query <string>("md5"), newABVersion[abName])) { // 添加到列表中 versionItemInfo.Add(abName, new List <object>() { newABVersion[abName], data.Query <int>("unzip_size"), data.Query <int>("zip_size") }); continue; } // 标识数据已经变化了 isABChanged = true; // 取得未压缩大小 unzipBuf = File.ReadAllBytes(string.Format("{0}{1}", encryptPath, abName)); if (unzipBuf.Length == 0) { NIDebug.Log(string.Format("读取{0}{1}失败!", encryptPath, abName)); continue; } NIEditorUtility.Zip(new string[] { string.Format("{0}{1}", encryptPath, abName) }, string.Format("{0}{1}_{2}.zip", publishPath, abName, newABVersion[abName])); // 读取文件 buf = File.ReadAllBytes(string.Format("{0}{1}_{2}.zip", publishPath, abName, newABVersion[abName])); if (buf.Length == 0) { NIDebug.Log(string.Format("读取{0}{1}失败!", publishPath, abName)); continue; } // 添加到列表中 versionItemInfo.Add(abName, new List <object>() { newABVersion[abName], unzipBuf.Length, buf.Length }); } // 如果ab资源没有变化, 不处理 if (isABChanged) { string resourceDictPath = string.Format("{0}{1}", encryptPath, "resource_dict.bytes"); // 发布资源到发布资源目录 string md5 = NIEditorUtility.GetFileMD5(resourceDictPath); // 取得未压缩大小 unzipBuf = File.ReadAllBytes(string.Format("{0}{1}", encryptPath, "resource_dict.bytes")); if (unzipBuf.Length == 0) { NIDebug.Log(string.Format("读取{0}{1}失败!", encryptPath, "resource_dict.bytes")); return; } NIEditorUtility.Zip(new string[] { string.Format("{0}{1}", encryptPath, "resource_dict.bytes") }, string.Format("{0}{1}_{2}.zip", publishPath, "resource_dict.bytes", md5)); // 读取文件 buf = File.ReadAllBytes(string.Format("{0}{1}_{2}.zip", publishPath, "resource_dict.bytes", md5)); if (buf.Length == 0) { NIDebug.Log(string.Format("读取{0}{1}失败!", publishPath, "resource_dict.bytes")); return; } // 添加到列表中 versionItemInfo.Add("resource_dict.bytes", new List <object>() { md5, unzipBuf.Length, buf.Length }); } bool isPatchChanged = false; Dictionary <string, string> abPatchDic = new Dictionary <string, string>(); // 生成压缩patch文件 Dictionary <string, string> newPatchVersion = GenPatchFiles(patchPath, encryptPath, versionItemInfo, ref abPatchDic); // 发布资源 foreach (string patchName in newPatchVersion.Keys) { // 获取旧版本信息 CsvRow data = oldVersionCsv.FindByKey(patchName); if ((data != null) && string.Equals(data.Query <string>("md5"), newPatchVersion[patchName])) { versionItemInfo.Add(patchName, new List <object>() { data.Query <string>("md5"), 0, data.Query <int>("zip_size") }); continue; } // 标识数据已经变化了 isPatchChanged = true; string filePath = string.Format("{0}{1}_{2}.zip", patchPath, patchName, newPatchVersion[patchName]); // 读取文件 buf = File.ReadAllBytes(filePath); if (buf.Length == 0) { NIDebug.LogError(string.Format("读取{0}失败!", filePath)); continue; } versionItemInfo.Add(patchName, new List <object>() { newPatchVersion[patchName], 0, buf.Length }); File.Copy(filePath, string.Format("{0}{1}_{2}.zip", publishPath, patchName, newPatchVersion[patchName]), true); } // 有变化重新生成版本文件 if (isABChanged || isPatchChanged) { // 将资源版本添加到列表中 versionItemInfo.Add("res_version", new List <object>() { resVersion, 0, 0 }); // 生成某个目录下的版本控制文件 GenVersionFile(abPath, publishPath, versionItemInfo, abPatchDic); } // 标识Build AssetBundle OK NIDebug.Log("生成AssetBundle完成"); // 刷新编辑器 AssetDatabase.Refresh(); }