using System; using System.Collections.Generic; using System.IO; using UnityEditor; namespace YooAsset.Editor { [TaskAttribute("创建构建报告文件")] public class TaskCreateReport : IBuildTask { void IBuildTask.Run(BuildContext context) { var buildParameters = context.GetContextObject<BuildParametersContext>(); var buildMapContext = context.GetContextObject<BuildMapContext>(); buildParameters.StopWatch(); var buildMode = buildParameters.Parameters.BuildMode; if (buildMode != EBuildMode.SimulateBuild) { CreateReportFile(buildParameters, buildMapContext); } float buildSeconds = buildParameters.GetBuildingSeconds(); BuildRunner.Info($"Build time consuming {buildSeconds} seconds."); } private void CreateReportFile(BuildParametersContext buildParameters, BuildMapContext buildMapContext) { PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(buildParameters.PipelineOutputDirectory, buildParameters.Parameters.BuildVersion); BuildReport buildReport = new BuildReport(); // 概述信息 { #if UNITY_2019_4_OR_NEWER UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(BuildReport).Assembly); if (packageInfo != null) buildReport.Summary.YooVersion = packageInfo.version; #endif buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion; buildReport.Summary.BuildDate = DateTime.Now.ToString(); buildReport.Summary.BuildSeconds = (int)buildParameters.GetBuildingSeconds(); buildReport.Summary.BuildTarget = buildParameters.Parameters.BuildTarget; buildReport.Summary.BuildPipeline = buildParameters.Parameters.BuildPipeline; 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.CopyBuildinTagFiles = buildParameters.Parameters.CopyBuildinTagFiles; buildReport.Summary.EncryptionServicesClassName = buildParameters.Parameters.EncryptionServices == null ? "null" : buildParameters.Parameters.EncryptionServices.GetType().FullName; // 构建参数 buildReport.Summary.OutputNameStyle = buildParameters.Parameters.OutputNameStyle; 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.MainAssetTotalCount = GetMainAssetCount(patchManifest); 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.FileSize; 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.FileName = patchBundle.FileName; reportBundleInfo.FileHash = patchBundle.FileHash; reportBundleInfo.FileCRC = patchBundle.FileCRC; reportBundleInfo.FileSize = patchBundle.FileSize; 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}"); } /// <summary> /// 获取资源对象依赖的所有资源包 /// </summary> private List<string> GetDependBundles(PatchManifest patchManifest, PatchAsset patchAsset) { List<string> dependBundles = new List<string>(patchAsset.DependIDs.Length); foreach (int index in patchAsset.DependIDs) { string dependBundleName = patchManifest.BundleList[index].BundleName; dependBundles.Add(dependBundleName); } return dependBundles; } /// <summary> /// 获取资源对象依赖的其它所有资源 /// </summary> private List<string> GetDependAssets(BuildMapContext buildMapContext, string bundleName, string assetPath) { List<string> result = new List<string>(); if (buildMapContext.TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo)) { BuildAssetInfo findAssetInfo = null; foreach (var buildinAsset in bundleInfo.BuildinAssets) { if (buildinAsset.AssetPath == assetPath) { findAssetInfo = buildinAsset; break; } } if (findAssetInfo == null) { throw new Exception($"Not found asset {assetPath} in bunlde {bundleName}"); } foreach (var dependAssetInfo in findAssetInfo.AllDependAssetInfos) { result.Add(dependAssetInfo.AssetPath); } } else { throw new Exception($"Not found bundle : {bundleName}"); } return result; } private int GetMainAssetCount(PatchManifest patchManifest) { return patchManifest.AssetList.Count; } private int GetAllBundleCount(PatchManifest patchManifest) { return patchManifest.BundleList.Count; } private long GetAllBundleSize(PatchManifest patchManifest) { long fileBytes = 0; foreach (var patchBundle in patchManifest.BundleList) { fileBytes += patchBundle.FileSize; } return fileBytes; } private int GetBuildinBundleCount(PatchManifest patchManifest) { int fileCount = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsBuildin) fileCount++; } return fileCount; } private long GetBuildinBundleSize(PatchManifest patchManifest) { long fileBytes = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsBuildin) fileBytes += patchBundle.FileSize; } return fileBytes; } private int GetEncryptedBundleCount(PatchManifest patchManifest) { int fileCount = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsEncrypted) fileCount++; } return fileCount; } private long GetEncryptedBundleSize(PatchManifest patchManifest) { long fileBytes = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsEncrypted) fileBytes += patchBundle.FileSize; } return fileBytes; } private int GetRawBundleCount(PatchManifest patchManifest) { int fileCount = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsRawFile) fileCount++; } return fileCount; } private long GetRawBundleSize(PatchManifest patchManifest) { long fileBytes = 0; foreach (var patchBundle in patchManifest.BundleList) { if (patchBundle.IsRawFile) fileBytes += patchBundle.FileSize; } return fileBytes; } } }