/// <summary> /// 从输出目录加载补丁清单文件 /// </summary> private PatchManifest LoadPatchManifestFile( ) { string filePath = $"{OutputDirectory}/{PatchDefine.PatchManifestFileName}"; if (File.Exists(filePath) == false) { return(new PatchManifest()); } string jsonData = FileUtility.ReadFile(filePath); return(PatchManifest.Deserialize(jsonData)); }
/// <summary> /// 3. 复制更新文件到补丁包目录 /// </summary> private void CopyUpdateFiles() { string packageFolderPath = GetPackageFolderPath(); Log($"开始复制更新文件到补丁包目录:{packageFolderPath}"); // 复制Readme文件 { string sourcePath = $"{OutputPath}/readme.txt"; string destPath = $"{packageFolderPath}/readme.txt"; EditorTools.CopyFile(sourcePath, destPath, true); Log($"复制Readme文件到:{destPath}"); } // 复制PatchManifest文件 { string sourcePath = $"{OutputPath}/{PatchDefine.PatchManifestFileName}"; string destPath = $"{packageFolderPath}/{PatchDefine.PatchManifestFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); Log($"复制PatchManifest文件到:{destPath}"); } // 复制UnityManifest文件 { string sourcePath = $"{OutputPath}/{PatchDefine.UnityManifestFileName}"; string destPath = $"{packageFolderPath}/{PatchDefine.UnityManifestFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); Log($"复制UnityManifest文件到:{destPath}"); } // 复制Manifest文件 { string sourcePath = $"{OutputPath}/{PatchDefine.UnityManifestFileName}.manifest"; string destPath = $"{packageFolderPath}/{PatchDefine.UnityManifestFileName}.manifest"; EditorTools.CopyFile(sourcePath, destPath, true); } // 复制所有更新文件 PatchManifest patchFile = LoadPatchManifestFile(); foreach (var pair in patchFile.Elements) { if (pair.Value.Version == BuildVersion) { string sourcePath = $"{OutputPath}/{pair.Key}"; string destPath = $"{packageFolderPath}/{pair.Key}"; EditorTools.CopyFile(sourcePath, destPath, true); Log($"复制更新文件:{destPath}"); } } }
/// <summary> /// 从输出目录加载补丁清单文件 /// </summary> private PatchManifest LoadPatchManifestFile() { string filePath = $"{OutputPath}/{PatchDefine.PatchManifestBytesFileName}"; PatchManifest patchFile = new PatchManifest(); // 如果文件不存在 if (File.Exists(filePath) == false) { return(patchFile); } byte[] fileData = File.ReadAllBytes(filePath); patchFile.Parse(fileData); return(patchFile); }
/// <summary> /// 获取资源包列表 /// </summary> private List <PatchBundle> GetAllPatchBundle(AssetBundleBuilder.BuildParametersContext buildParameters, TaskGetBuildMap.BuildMapContext buildMapContext, TaskEncryption.EncryptionContext encryptionContext, AssetBundleManifest unityManifest) { List <PatchBundle> result = new List <PatchBundle>(); // 加载DLC DLCManager dlcManager = new DLCManager(); dlcManager.LoadAllDLC(); // 加载旧补丁清单 PatchManifest oldPatchManifest = AssetBundleBuilder.LoadPatchManifestFile(buildParameters); // 获取加密列表 List <string> encryptList = encryptionContext.EncryptList; string[] allAssetBundles = unityManifest.GetAllAssetBundles(); foreach (var bundleName in allAssetBundles) { string path = $"{buildParameters.OutputDirectory}/{bundleName}"; string hash = HashUtility.FileMD5(path); string crc = HashUtility.FileCRC32(path); long size = FileUtility.GetFileSize(path); int version = buildParameters.BuildVersion; string[] assets = buildMapContext.GetCollectAssetPaths(bundleName); string[] depends = unityManifest.GetDirectDependencies(bundleName); string[] dlcLabels = dlcManager.GetAssetBundleDLCLabels(bundleName); // 创建标记位 bool isEncrypted = encryptList.Contains(bundleName); int flags = PatchBundle.CreateFlags(isEncrypted); // 注意:如果文件没有变化使用旧版本号 if (oldPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle oldElement)) { if (oldElement.Hash == hash) { version = oldElement.Version; } } PatchBundle newElement = new PatchBundle(bundleName, hash, crc, size, version, flags, assets, depends, dlcLabels); result.Add(newElement); } return(result); }
/// <summary> /// 获取资源包列表 /// </summary> private List <PatchBundle> GetAllPatchBundle(AssetBundleBuilder.BuildParametersContext buildParameters, TaskGetBuildMap.BuildMapContext buildMapContext, TaskEncryption.EncryptionContext encryptionContext, AssetBundleManifest unityManifest) { List <PatchBundle> result = new List <PatchBundle>(); // 内置标记列表 List <string> buildinTags = buildParameters.Parameters.GetBuildinTags(); // 加载旧补丁清单 PatchManifest oldPatchManifest = null; if (buildParameters.Parameters.IsForceRebuild == false) { oldPatchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory); } string[] allAssetBundles = unityManifest.GetAllAssetBundles(); foreach (var bundleName in allAssetBundles) { string path = $"{buildParameters.PipelineOutputDirectory}/{bundleName}"; string hash = HashUtility.FileMD5(path); string crc = HashUtility.FileCRC32(path); long size = FileUtility.GetFileSize(path); int version = buildParameters.Parameters.BuildVersion; string[] collectAssets = buildMapContext.GetCollectAssetPaths(bundleName); string[] depends = unityManifest.GetDirectDependencies(bundleName); string[] tags = buildMapContext.GetAssetTags(bundleName); bool isEncrypted = encryptionContext.IsEncryptFile(bundleName); bool isBuildin = IsBuildinBundle(tags, buildinTags); // 注意:如果文件没有变化使用旧版本号 if (oldPatchManifest != null && oldPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle value)) { if (value.Hash == hash) { version = value.Version; } } PatchBundle patchBundle = new PatchBundle(bundleName, hash, crc, size, version, collectAssets, depends, tags); patchBundle.SetFlagsValue(isEncrypted, isBuildin); result.Add(patchBundle); } return(result); }
/// <summary> /// 创建补丁清单文件到输出目录 /// </summary> private void CreatePatchManifestFile(AssetBundleBuilder.BuildParametersContext buildParameters, TaskGetBuildMap.BuildMapContext buildMapContext, TaskEncryption.EncryptionContext encryptionContext, AssetBundleManifest unityManifest) { // 创建新补丁清单 PatchManifest patchManifest = new PatchManifest(); patchManifest.ResourceVersion = buildParameters.BuildVersion; patchManifest.BundleList = GetAllPatchBundle(buildParameters, buildMapContext, encryptionContext, unityManifest); patchManifest.VariantList = GetAllPatchVariant(unityManifest); // 创建新文件 string filePath = $"{buildParameters.OutputDirectory}/{PatchDefine.PatchManifestFileName}"; BuildLogger.Log($"创建补丁清单文件:{filePath}"); PatchManifest.Serialize(filePath, patchManifest); }
private void CopyBuildinFilesToStreaming(string pipelineOutputDirectory, int buildVersion) { // 加载补丁清单 PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(pipelineOutputDirectory, buildVersion); // 拷贝文件列表 foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsBuildin == false) { continue; } string sourcePath = $"{pipelineOutputDirectory}/{patchBundle.BundleName}"; string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{patchBundle.Hash}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝清单文件 { string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(buildVersion)}"; string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{YooAssetSettingsData.GetPatchManifestFileName(buildVersion)}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝清单哈希文件 { string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestHashFileName(buildVersion)}"; string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{YooAssetSettingsData.GetPatchManifestHashFileName(buildVersion)}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝静态版本文件 { string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettings.VersionFileName}"; string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{YooAssetSettings.VersionFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 刷新目录 AssetDatabase.Refresh(); BuildRunner.Log($"内置文件拷贝完成:{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}"); }
/// <summary> /// 复制所有补丁包文件到流目录 /// </summary> /// <param name="targetVersion">目标版本。如果版本为负值则拷贝所有版本</param> public static void CopyPackageToStreamingFolder(BuildTarget buildTarget, string outputRoot, int targetVersion = -1) { // 补丁清单路径 string filePath = $"{outputRoot}/{buildTarget}/{PatchDefine.UnityManifestFileName}/{PatchDefine.PatchManifestFileName}"; if (File.Exists(filePath) == false) { throw new System.Exception($"Not found {PatchDefine.PatchManifestFileName} file : {filePath}"); } // 加载补丁清单 string jsonData = FileUtility.ReadFile(filePath); PatchManifest pm = PatchManifest.Deserialize(jsonData); // 拷贝文件列表 foreach (var element in pm.ElementList) { if (element.IsDLC()) { continue; } if (targetVersion >= 0 && element.Version > targetVersion) { continue; } string sourcePath = $"{outputRoot}/{buildTarget}/{element.Version}/{element.Name}"; string destPath = $"{Application.dataPath}/StreamingAssets/{element.Name}"; Debug.Log($"拷贝版本文件到流目录:{destPath}"); EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝核心文件 { string destFilePath = $"{Application.dataPath}/StreamingAssets/{PatchDefine.PatchManifestFileName}"; EditorTools.CopyFile(filePath, destFilePath, true); } // 刷新目录 AssetDatabase.Refresh(); }
/// <summary> /// 从输出目录加载补丁清单文件 /// </summary> private PatchManifest LoadPatchManifestFile() { string filePath = $"{OutputPath}/{PatchDefine.PatchManifestFileName}"; PatchManifest patchFile = new PatchManifest(); // 如果文件不存在 if (File.Exists(filePath) == false) { return(patchFile); } using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { StreamReader sr = new StreamReader(fs); patchFile.Parse(sr); sr.Close(); fs.Close(); } return(patchFile); }
/// <summary> /// Reads the manifest file which should be included in every .patch file. /// </summary> /// <param name="patchFileDirectory">the directory in which the manifest file exists</param> /// <returns>the differences indicated in the manifest.</returns> private static PatchManifest ReadPatchManifest(string patchFileDirectory) { PatchManifest manifest = new PatchManifest(); BinaryReader r = null; try { FileStream fs = new FileStream(patchFileDirectory + "\\manifest", FileMode.Open, FileAccess.Read, FileShare.Read); r = new BinaryReader(fs); manifest.FromVersionNumber = r.ReadString(); manifest.ToVersionNumber = r.ReadString(); manifest.PatchNotes = r.ReadString(); while (r.PeekChar() > -1) { DiffType dt = (DiffType)r.ReadInt32(); string file = r.ReadString(); Diff diff = new Diff(dt, file); diff.HashedFilename = r.ReadString(); manifest.Differences.Add(diff); } } catch { } finally { if (r != null) { r.Close(); } } return(manifest); }
/// <summary> /// 3. 创建Readme文件到输出目录 /// </summary> private void CreateReadmeFile(AssetBundleManifest unityManifest) { string[] allAssetBundles = unityManifest.GetAllAssetBundles(); // 删除旧文件 string filePath = $"{OutputDirectory}/{PatchDefine.ReadmeFileName}"; if (File.Exists(filePath)) { File.Delete(filePath); } Log($"创建说明文件:{filePath}"); StringBuilder content = new StringBuilder(); AppendData(content, $"构建平台:{BuildTarget}"); AppendData(content, $"构建版本:{BuildVersion}"); AppendData(content, $"构建时间:{DateTime.Now}"); AppendData(content, ""); AppendData(content, $"--配置信息--"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { AssetBundleCollectorSetting.Collector wrapper = AssetBundleCollectorSettingData.Setting.Collectors[i]; AppendData(content, $"Directory : {wrapper.CollectDirectory} || CollectRule : {wrapper.CollectRule} || CollectorName : {wrapper.CollectorName}"); } AppendData(content, ""); AppendData(content, $"--构建参数--"); AppendData(content, $"CompressOption:{CompressOption}"); AppendData(content, $"ForceRebuild:{IsForceRebuild}"); AppendData(content, $"DisableWriteTypeTree:{IsDisableWriteTypeTree}"); AppendData(content, $"IgnoreTypeTreeChanges:{IsIgnoreTypeTreeChanges}"); AppendData(content, ""); AppendData(content, $"--构建清单--"); for (int i = 0; i < allAssetBundles.Length; i++) { AppendData(content, allAssetBundles[i]); } PatchManifest patchFile = LoadPatchManifestFile(); { AppendData(content, ""); AppendData(content, $"--更新清单--"); foreach (var element in patchFile.ElementList) { if (element.Version == BuildVersion) { AppendData(content, element.BundleName); } } AppendData(content, ""); AppendData(content, $"--变体列表--"); foreach (var variant in patchFile.VariantList) { AppendData(content, variant.ToString()); } } // 创建新文件 File.WriteAllText(filePath, content.ToString(), Encoding.UTF8); }
/// <summary> /// 1. 创建补丁清单文件到输出目录 /// </summary> private void CreatePatchManifestFile(string[] allAssetBundles) { // 加载旧文件 PatchManifest patchManifest = LoadPatchManifestFile(); // 删除旧文件 string filePath = OutputPath + $"/{PatchDefine.PatchManifestFileName}"; if (File.Exists(filePath)) { File.Delete(filePath); } // 创建新文件 Log($"创建补丁清单文件:{filePath}"); using (FileStream fs = File.Create(filePath)) { StreamWriter sw = new StreamWriter(fs); // 写入版本信息 sw.Write(BuildVersion); sw.Write("\n"); sw.Flush(); // 写入UnityManifest文件的信息 { string assetName = PatchDefine.UnityManifestFileName; string path = $"{OutputPath}/{assetName}"; string md5 = HashUtility.FileMD5(path); long sizeBytes = EditorTools.GetFileSize(path); int version = BuildVersion; sw.Write($"{assetName}={md5}={sizeBytes}={version}"); sw.Write("\n"); sw.Flush(); } // 写入所有AssetBundle文件的信息 foreach (string assetName in allAssetBundles) { string path = $"{OutputPath}/{assetName}"; string md5 = HashUtility.FileMD5(path); long sizeBytes = EditorTools.GetFileSize(path); int version = BuildVersion; // 注意:如果文件没有变化使用旧版本号 PatchElement element; if (patchManifest.Elements.TryGetValue(assetName, out element)) { if (element.MD5 == md5) { version = element.Version; } } sw.Write($"{assetName}={md5}={sizeBytes}={version}"); sw.Write("\n"); sw.Flush(); } // 关闭文件流 sw.Close(); fs.Close(); } }
/// <summary> /// 拷贝补丁文件到补丁包目录 /// </summary> private void CopyPatchFiles(AssetBundleBuilder.BuildParametersContext buildParameters) { int resourceVersion = buildParameters.Parameters.BuildVersion; string packageDirectory = buildParameters.GetPackageDirectory(); BuildRunner.Log($"开始拷贝补丁文件到补丁包目录:{packageDirectory}"); // 拷贝Report文件 { string reportFileName = YooAssetSettingsData.GetReportFileName(buildParameters.Parameters.BuildVersion); string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{reportFileName}"; string destPath = $"{packageDirectory}/{reportFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝补丁清单文件 { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(resourceVersion)}"; string destPath = $"{packageDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(resourceVersion)}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝补丁清单哈希文件 { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.GetPatchManifestHashFileName(resourceVersion)}"; string destPath = $"{packageDirectory}/{YooAssetSettingsData.GetPatchManifestHashFileName(resourceVersion)}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝静态版本文件 { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettings.VersionFileName}"; string destPath = $"{packageDirectory}/{YooAssetSettings.VersionFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝UnityManifest序列化文件 { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}"; string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝UnityManifest文本文件 { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest"; string destPath = $"{packageDirectory}/{YooAssetSettingsData.Setting.UnityManifestFileName}.manifest"; EditorTools.CopyFile(sourcePath, destPath, true); } // 拷贝所有补丁文件 int progressValue = 0; PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory, buildParameters.Parameters.BuildVersion); int patchFileTotalCount = patchManifest.BundleList.Count; foreach (var patchBundle in patchManifest.BundleList) { string sourcePath = $"{buildParameters.PipelineOutputDirectory}/{patchBundle.BundleName}"; string destPath = $"{packageDirectory}/{patchBundle.Hash}"; EditorTools.CopyFile(sourcePath, destPath, true); EditorTools.DisplayProgressBar("拷贝补丁文件", ++progressValue, patchFileTotalCount); } EditorTools.ClearProgressBar(); }
/// <summary> /// 2. 创建补丁清单文件到输出目录 /// </summary> private void CreatePatchManifestFile(AssetBundleManifest unityManifest, List <AssetInfo> buildMap, List <string> encryptList) { string[] allAssetBundles = unityManifest.GetAllAssetBundles(); // 创建DLC管理器 DLCManager dlcManager = new DLCManager(); dlcManager.LoadAllDLC(); // 加载旧补丁清单 PatchManifest oldPatchManifest = LoadPatchManifestFile(); // 创建新补丁清单 PatchManifest newPatchManifest = new PatchManifest(); // 写入版本信息 newPatchManifest.ResourceVersion = BuildVersion; // 写入所有AssetBundle文件的信息 for (int i = 0; i < allAssetBundles.Length; i++) { string bundleName = allAssetBundles[i]; string path = $"{OutputDirectory}/{bundleName}"; string md5 = HashUtility.FileMD5(path); uint crc32 = HashUtility.FileCRC32(path); long sizeBytes = EditorTools.GetFileSize(path); int version = BuildVersion; string[] assetPaths = GetBundleAssetPaths(buildMap, bundleName); string[] depends = unityManifest.GetDirectDependencies(bundleName); string[] dlcLabels = dlcManager.GetAssetBundleDLCLabels(bundleName); // 创建标记位 bool isEncrypted = encryptList.Contains(bundleName); bool isCollected = IsCollectBundle(buildMap, bundleName); int flags = PatchElement.CreateFlags(isEncrypted, isCollected); // 注意:如果文件没有变化使用旧版本号 if (oldPatchManifest.Elements.TryGetValue(bundleName, out PatchElement oldElement)) { if (oldElement.MD5 == md5) { version = oldElement.Version; } } PatchElement newElement = new PatchElement(bundleName, md5, crc32, sizeBytes, version, flags, assetPaths, depends, dlcLabels); newPatchManifest.ElementList.Add(newElement); } // 写入所有变体信息 { Dictionary <string, List <string> > variantInfos = GetVariantInfos(allAssetBundles); foreach (var pair in variantInfos) { if (pair.Value.Count > 0) { string bundleName = $"{pair.Key}.{ PatchDefine.AssetBundleDefaultVariant}"; List <string> variants = pair.Value; newPatchManifest.VariantList.Add(new PatchVariant(bundleName, variants)); } } } // 创建新文件 string filePath = OutputDirectory + $"/{PatchDefine.PatchManifestFileName}"; Log($"创建补丁清单文件:{filePath}"); PatchManifest.Serialize(filePath, newPatchManifest); }
void IBuildTask.Run(BuildContext context) { var buildParameters = context.GetContextObject <AssetBundleBuilder.BuildParametersContext>(); // 检测构建平台是否合法 if (buildParameters.Parameters.BuildTarget == BuildTarget.NoTarget) { throw new Exception("请选择目标平台"); } // 检测构建版本是否合法 if (buildParameters.Parameters.BuildVersion <= 0) { throw new Exception("请先设置版本号"); } // 检测输出目录是否为空 if (string.IsNullOrEmpty(buildParameters.PipelineOutputDirectory)) { throw new Exception("输出目录不能为空"); } // 检测资源收集配置文件 if (AssetBundleCollectorSettingData.GetCollecterCount() == 0) { throw new Exception("配置的资源收集路径为空"); } // 增量更新时候的必要检测 if (buildParameters.Parameters.IsForceRebuild == false) { // 检测历史版本是否存在 if (AssetBundleBuilderHelper.HasAnyPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot) == false) { throw new Exception("没有发现任何历史版本,请尝试强制重建"); } // 检测构建版本是否合法 int maxPackageVersion = AssetBundleBuilderHelper.GetMaxPackageVersion(buildParameters.Parameters.BuildTarget, buildParameters.Parameters.OutputRoot); if (buildParameters.Parameters.BuildVersion <= maxPackageVersion) { throw new Exception("构建版本不能小于历史版本"); } // 检测补丁包是否已经存在 string packageDirectory = buildParameters.GetPackageDirectory(); if (Directory.Exists(packageDirectory)) { throw new Exception($"补丁包已经存在:{packageDirectory}"); } // 检测内置资源标记是否一致 PatchManifest oldPatchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory); if (buildParameters.Parameters.BuildinTags != oldPatchManifest.BuildinTags) { throw new Exception($"增量更新时内置资源标记必须一致:{buildParameters.Parameters.BuildinTags} != {oldPatchManifest.BuildinTags}"); } } // 如果是强制重建 if (buildParameters.Parameters.IsForceRebuild) { // 删除平台总目录 string platformDirectory = $"{buildParameters.Parameters.OutputRoot}/{buildParameters.Parameters.BuildTarget}"; if (EditorTools.DeleteDirectory(platformDirectory)) { BuildLogger.Log($"删除平台总目录:{platformDirectory}"); } } // 如果输出目录不存在 if (EditorTools.CreateDirectory(buildParameters.PipelineOutputDirectory)) { BuildLogger.Log($"创建输出目录:{buildParameters.PipelineOutputDirectory}"); } }
private void CreateReportFile(AssetBundleBuilder.BuildParametersContext buildParameters, BuildMapContext buildMapContext) { PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory, buildParameters.Parameters.BuildVersion); BuildReport buildReport = new BuildReport(); // 概述信息 { buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion; buildReport.Summary.BuildTime = DateTime.Now.ToString(); buildReport.Summary.BuildSeconds = (int)buildParameters.GetBuildingSeconds(); buildReport.Summary.BuildTarget = buildParameters.Parameters.BuildTarget; buildReport.Summary.BuildMode = buildParameters.Parameters.BuildMode; buildReport.Summary.BuildVersion = buildParameters.Parameters.BuildVersion; buildReport.Summary.BuildinTags = buildParameters.Parameters.BuildinTags; buildReport.Summary.EnableAddressable = buildParameters.Parameters.EnableAddressable; buildReport.Summary.AppendFileExtension = buildParameters.Parameters.AppendFileExtension; buildReport.Summary.CopyBuildinTagFiles = buildParameters.Parameters.CopyBuildinTagFiles; buildReport.Summary.AutoCollectShaders = AssetBundleCollectorSettingData.Setting.AutoCollectShaders; buildReport.Summary.ShadersBundleName = AssetBundleCollectorSettingData.Setting.ShadersBundleName; buildReport.Summary.EncryptionServicesClassName = buildParameters.Parameters.EncryptionServices == null ? "null" : buildParameters.Parameters.EncryptionServices.GetType().FullName; // 构建参数 buildReport.Summary.CompressOption = buildParameters.Parameters.CompressOption; buildReport.Summary.DisableWriteTypeTree = buildParameters.Parameters.DisableWriteTypeTree; buildReport.Summary.IgnoreTypeTreeChanges = buildParameters.Parameters.IgnoreTypeTreeChanges; // 构建结果 buildReport.Summary.AssetFileTotalCount = buildMapContext.AssetFileCount; buildReport.Summary.AllBundleTotalCount = GetAllBundleCount(patchManifest); buildReport.Summary.AllBundleTotalSize = GetAllBundleSize(patchManifest); buildReport.Summary.BuildinBundleTotalCount = GetBuildinBundleCount(patchManifest); buildReport.Summary.BuildinBundleTotalSize = GetBuildinBundleSize(patchManifest); buildReport.Summary.EncryptedBundleTotalCount = GetEncryptedBundleCount(patchManifest); buildReport.Summary.EncryptedBundleTotalSize = GetEncryptedBundleSize(patchManifest); buildReport.Summary.RawBundleTotalCount = GetRawBundleCount(patchManifest); buildReport.Summary.RawBundleTotalSize = GetRawBundleSize(patchManifest); } // 资源对象列表 buildReport.AssetInfos = new List <ReportAssetInfo>(patchManifest.AssetList.Count); foreach (var patchAsset in patchManifest.AssetList) { var mainBundle = patchManifest.BundleList[patchAsset.BundleID]; ReportAssetInfo reportAssetInfo = new ReportAssetInfo(); reportAssetInfo.Address = patchAsset.Address; reportAssetInfo.AssetPath = patchAsset.AssetPath; reportAssetInfo.AssetTags = patchAsset.AssetTags; reportAssetInfo.AssetGUID = AssetDatabase.AssetPathToGUID(patchAsset.AssetPath); reportAssetInfo.MainBundleName = mainBundle.BundleName; reportAssetInfo.MainBundleSize = mainBundle.SizeBytes; reportAssetInfo.DependBundles = GetDependBundles(patchManifest, patchAsset); reportAssetInfo.DependAssets = GetDependAssets(buildMapContext, mainBundle.BundleName, patchAsset.AssetPath); buildReport.AssetInfos.Add(reportAssetInfo); } // 资源包列表 buildReport.BundleInfos = new List <ReportBundleInfo>(patchManifest.BundleList.Count); foreach (var patchBundle in patchManifest.BundleList) { ReportBundleInfo reportBundleInfo = new ReportBundleInfo(); reportBundleInfo.BundleName = patchBundle.BundleName; reportBundleInfo.Hash = patchBundle.Hash; reportBundleInfo.CRC = patchBundle.CRC; reportBundleInfo.SizeBytes = patchBundle.SizeBytes; reportBundleInfo.Tags = patchBundle.Tags; reportBundleInfo.Flags = patchBundle.Flags; buildReport.BundleInfos.Add(reportBundleInfo); } // 删除旧文件 string filePath = $"{buildParameters.PipelineOutputDirectory}/{YooAssetSettingsData.GetReportFileName(buildParameters.Parameters.BuildVersion)}"; if (File.Exists(filePath)) { File.Delete(filePath); } // 序列化文件 BuildReport.Serialize(filePath, buildReport); BuildRunner.Log($"资源构建报告文件创建完成:{filePath}"); }
private int GetAllBundleCount(PatchManifest patchManifest) { return(patchManifest.BundleList.Count); }
private void CreatePatchManifestBytesFile(string[] allAssetBundles, Dictionary <string, List <string> > variantInfos) { ByteBuffer fileBuffer = new ByteBuffer(PatchManifest.FileStreamMaxLen); ByteBuffer tableBuffer = new ByteBuffer(PatchManifest.TableStreamMaxLen); // 加载补丁清单 PatchManifest oldPatchManifest = LoadPatchManifestFile(); // 删除旧文件 string filePath = OutputPath + $"/{PatchDefine.PatchManifestBytesFileName}"; if (File.Exists(filePath)) { File.Delete(filePath); } // 创建新文件 Log($"创建补丁清单文件:{filePath}"); // 写入版本信息 fileBuffer.WriteInt(BuildVersion); // 写入元素总数 fileBuffer.WriteInt(allAssetBundles.Length + 1); // 写入UnityManifest文件的信息 { string assetName = PatchDefine.UnityManifestFileName; string path = $"{OutputPath}/{assetName}"; string md5 = HashUtility.FileMD5(path); long sizeBytes = EditorTools.GetFileSize(path); int version = BuildVersion; List <string> variantList = null; tableBuffer.Clear(); tableBuffer.WriteUTF(assetName); tableBuffer.WriteUTF(md5); tableBuffer.WriteLong(sizeBytes); tableBuffer.WriteInt(version); tableBuffer.WriteListUTF(variantList); // 写入到总缓存 int tabSize = tableBuffer.ReadableBytes(); fileBuffer.WriteShort(PatchManifest.TableStreamHead); fileBuffer.WriteInt(tabSize); fileBuffer.WriteBytes(tableBuffer.ReadBytes(tabSize)); } // 写入所有AssetBundle文件的信息 foreach (string assetName in allAssetBundles) { string path = $"{OutputPath}/{assetName}"; string md5 = HashUtility.FileMD5(path); long sizeBytes = EditorTools.GetFileSize(path); int version = BuildVersion; string variants = GetVariants(variantInfos, assetName); List <string> variantList = null; if (string.IsNullOrEmpty(variants) == false) { variantList = variants.Split('|').ToList(); } // 注意:如果文件没有变化使用旧版本号 if (oldPatchManifest.Elements.TryGetValue(assetName, out PatchElement element)) { if (element.MD5 == md5) { version = element.Version; } } tableBuffer.Clear(); tableBuffer.WriteUTF(assetName); tableBuffer.WriteUTF(md5); tableBuffer.WriteLong(sizeBytes); tableBuffer.WriteInt(version); tableBuffer.WriteListUTF(variantList); // 写入到总缓存 int tabSize = tableBuffer.ReadableBytes(); fileBuffer.WriteShort(PatchManifest.TableStreamHead); fileBuffer.WriteInt(tabSize); fileBuffer.WriteBytes(tableBuffer.ReadBytes(tabSize)); } // 创建文件 using (FileStream fs = new FileStream(filePath, FileMode.Create)) { byte[] data = fileBuffer.Buf; int length = fileBuffer.ReadableBytes(); fs.Write(data, 0, length); } }
/// <summary> /// 创建Readme文件到输出目录 /// </summary> private void CreateReadmeFile(AssetBundleBuilder.BuildParametersContext buildParameters, AssetBundleBuilder.BuildOptionsContext buildOptions, AssetBundleManifest unityManifest) { string[] allAssetBundles = unityManifest.GetAllAssetBundles(); // 删除旧文件 string filePath = $"{buildParameters.OutputDirectory}/{PatchDefine.ReadmeFileName}"; if (File.Exists(filePath)) { File.Delete(filePath); } BuildLogger.Log($"创建说明文件:{filePath}"); StringBuilder content = new StringBuilder(); AppendData(content, $"构建平台:{buildParameters.BuildTarget}"); AppendData(content, $"构建版本:{buildParameters.BuildVersion}"); AppendData(content, $"构建时间:{DateTime.Now}"); AppendData(content, ""); AppendData(content, $"--着色器--"); AppendData(content, $"IsCollectAllShaders:{AssetBundleCollectorSettingData.Setting.IsCollectAllShaders}"); AppendData(content, $"ShadersBundleName:{AssetBundleCollectorSettingData.Setting.ShadersBundleName}"); AppendData(content, ""); AppendData(content, $"--配置信息--"); for (int i = 0; i < AssetBundleCollectorSettingData.Setting.Collectors.Count; i++) { AssetBundleCollectorSetting.Collector wrapper = AssetBundleCollectorSettingData.Setting.Collectors[i]; AppendData(content, $"Directory : {wrapper.CollectDirectory} | {wrapper.PackRuleClassName} | {wrapper.FilterRuleClassName}"); } AppendData(content, ""); AppendData(content, $"--构建参数--"); AppendData(content, $"CompressOption:{buildOptions.CompressOption}"); AppendData(content, $"IsForceRebuild:{buildOptions.IsForceRebuild}"); AppendData(content, $"IsDisableWriteTypeTree:{buildOptions.IsDisableWriteTypeTree}"); AppendData(content, $"IsIgnoreTypeTreeChanges:{buildOptions.IsIgnoreTypeTreeChanges}"); AppendData(content, ""); AppendData(content, $"--构建清单--"); for (int i = 0; i < allAssetBundles.Length; i++) { AppendData(content, allAssetBundles[i]); } PatchManifest patchFile = AssetBundleBuilder.LoadPatchManifestFile(buildParameters); { AppendData(content, ""); AppendData(content, $"--更新清单--"); foreach (var patchBundle in patchFile.BundleList) { if (patchBundle.Version == buildParameters.BuildVersion) { AppendData(content, patchBundle.BundleName); } } AppendData(content, ""); AppendData(content, $"--变体列表--"); foreach (var variant in patchFile.VariantList) { AppendData(content, variant.ToString()); } } // 创建新文件 File.WriteAllText(filePath, content.ToString(), Encoding.UTF8); }
private int[] GetAssetBundleDependIDs(int mainBundleID, BuildAssetInfo assetInfo, PatchManifest patchManifest) { List <int> result = new List <int>(); foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos) { if (dependAssetInfo.HasBundleName()) { int bundleID = GetAssetBundleID(dependAssetInfo.GetBundleName(), patchManifest); if (mainBundleID != bundleID) { if (result.Contains(bundleID) == false) { result.Add(bundleID); } } } } return(result.ToArray()); }