
源码-清单与报告篇章04-源码深度-编辑器模块阅读时间约 25 分钟前置知识了解构建管线分析一、引言本章将深入解析 YooAsset 清单Manifest与报告Report的源码实现。PackageManifest 是 YooAsset Editor 端和 Runtime 端之间的数据桥梁记录了所有 Bundle 的信息BuildReport 记录了构建的详细信息是开发者分析构建结果的重要依据。本章将从源码层面深入解析 PackageManifest 和 BuildReport 的设计与实现。二、PackageManifest 概述2.1 PackageManifest 的作用PackageManifest 是 YooAsset 的资源清单在整个资源管理流程中起到核心作用数据桥梁PackageManifest 是 Editor 端和 Runtime 端之间的数据桥梁。Editor 端生成 PackageManifestRuntime 端读取 PackageManifest。资源定位PackageManifest 记录了所有资源地址到 Bundle 的映射关系运行时通过 PackageManifest 定位资源。依赖管理PackageManifest 记录了 Bundle 之间的依赖关系运行时可以根据依赖关系加载 Bundle。版本管理PackageManifest 包含版本信息支持热更新时的版本比较。加密信息PackageManifest 包含加密信息运行时根据加密信息解密资源。2.2 PackageManifest 的核心字段[Serializable] public class PackageManifest { // 包名 public string PackageName; // 包版本 public string PackageVersion; // 包描述 public string PackageDesc; // 资源版本用于热更新 public string ResourceVersion; // 构建时间 public long BuildTime; // 构建引擎版本 public string BuildEngineVersion; // 资源清单 public AssetList AssetList new AssetList(); // Bundle 列表 public BundleList BundleList new BundleList(); } [Serializable] public class AssetList { public ListPackageAsset Assets new ListPackageAsset(); } [Serializable] public class PackageAsset { public string Address; // 资源地址 public string AssetPath; // 资源路径 public string AssetGUID; // 资源 GUID public int BundleID; // 所属 Bundle ID public int DependIDs; // 依赖的 Bundle ID 列表 public string AssetTags; // 资源标签 } [Serializable] public class BundleList { public ListPackageBundle Bundles new ListPackageBundle(); } [Serializable] public class PackageBundle { public int BundleID; // Bundle ID public string BundleName; // Bundle 名称 public string FileName; // Bundle 文件名 public string FileHash; // Bundle 文件 Hash public long FileSize; // Bundle 文件大小 public string FileCRC; // Bundle 文件 CRC public bool Encrypted; // 是否加密 public EBundleType BundleType; // Bundle 类型 public Listint DependIDs; // 依赖的 Bundle ID 列表 }PackageName 详解PackageName 是 Package 的唯一标识符。运行时通过 PackageName 加载 Package。PackageVersion 详解PackageVersion 是 Package 的版本号用于热更新时的版本比较。ResourceVersion 详解ResourceVersion 是资源版本号可以与 PackageVersion 不同。用于更细粒度的版本管理。AssetList 详解AssetList 包含了所有资源的信息包括资源地址、路径、Bundle 等。BundleList 详解BundleList 包含了所有 Bundle 的信息包括 Bundle 名称、文件信息、依赖关系等。2.3 PackageManifest 的序列化PackageManifest 使用 JSON 格式序列化public class PackageManifest { public string ToJson() { return JsonUtility.ToJson(this, true); } public static PackageManifest FromJson(string json) { return JsonUtility.FromJsonPackageManifest(json); } public void SaveToFile(string filePath) { string json ToJson(); File.WriteAllText(filePath, json); } public static PackageManifest LoadFromFile(string filePath) { string json File.ReadAllText(filePath); return FromJson(json); } }JSON 序列化详解使用 Unity 的 JsonUtility 进行 JSON 序列化。JsonUtility 支持 [Serializable] 特性的类。JSON 文件存储详解PackageManifest 通常保存为PackageManifest_{PackageVersion}.bytes或PackageManifest_{PackageVersion}.json文件。序列化的兼容性JsonUtility 的序列化是向前兼容的。新版本可以读取旧版本的 JSON但旧版本可能无法读取新版本。三、PackageManifest 生成流程3.1 生成流程概述PackageManifest 的生成流程PackageManifest 生成流程 1. 收集所有 Bundle 信息 2. 收集所有资源信息 3. 建立资源到 Bundle 的映射 4. 建立 Bundle 依赖关系 5. 计算资源地址 6. 计算 Bundle Hash 和大小 7. 序列化为 JSON 8. 写入输出文件收集 Bundle 信息详解从 BuildMap 中收集所有 Bundle 的信息包括 Bundle 名称、文件、依赖等。收集资源信息详解从 BuildMap 中收集所有资源的信息包括资源地址、路径、Bundle 等。建立映射详解建立资源地址到 Bundle 的映射便于运行时通过资源地址定位 Bundle。建立依赖关系详解建立 Bundle 之间的依赖关系便于运行时加载依赖的 Bundle。计算 Hash 和大小详解计算 Bundle 文件的 Hash 和大小用于版本管理和完整性验证。3.2 BuildTaskCreateManifestBuildTaskCreateManifest 是创建 PackageManifest 的构建任务public class BuildTaskCreateManifest : IBuildTask { public void Run(BuildContext context) { PackageManifest manifest new PackageManifest(); // 1. 填充基本信息 manifest.PackageName context.Parameters.PackageName; manifest.PackageVersion context.Parameters.PackageVersion; manifest.ResourceVersion context.Parameters.ResourceVersion; manifest.BuildTime DateTimeOffset.UtcNow.ToUnixTimeSeconds(); manifest.BuildEngineVersion Application.unityVersion; // 2. 创建 Bundle 列表 foreach (var buildBundle in context.BuildMap.Bundles) { var packageBundle new PackageBundle(); packageBundle.BundleID manifest.BundleList.Bundles.Count; packageBundle.BundleName buildBundle.BundleName; packageBundle.FileName buildBundle.FileName; packageBundle.FileHash buildBundle.Hash; packageBundle.FileSize buildBundle.FileSize; packageBundle.FileCRC buildBundle.CRC; packageBundle.Encrypted context.Parameters.EnableEncryption; packageBundle.BundleType buildBundle.BundleType; packageBundle.DependIDs ConvertDependNamesToIds(buildBundle.Dependencies, manifest); manifest.BundleList.Bundles.Add(packageBundle); } // 3. 创建资源列表 foreach (var assetEntry in context.BuildMap.AssetToBundle) { var packageAsset new PackageAsset(); packageAsset.Address assetEntry.Key; packageAsset.AssetPath assetEntry.Value.AssetPath; packageAsset.AssetGUID assetEntry.Value.AssetGUID; packageAsset.BundleID GetBundleId(assetEntry.Value.BundleName, manifest); packageAsset.DependIDs GetDependIds(assetEntry.Value.Dependencies, manifest); packageAsset.AssetTags string.Join(,, assetEntry.Value.AssetTags); manifest.AssetList.Assets.Add(packageAsset); } // 4. 保存到文件 manifest.SaveToFile(context.ManifestFilePath); } }填充基本信息详解填充 PackageManifest 的基本信息包括包名、版本、构建时间等。创建 Bundle 列表详解将 BuildMap 中的 Bundle 转换为 PackageBundle并建立 Bundle ID。创建资源列表详解将 BuildMap 中的资源转换为 PackageAsset并设置 Bundle ID。保存到文件详解将 PackageManifest 序列化为 JSON 并保存到输出文件。3.3 资源地址计算资源地址是 PackageManifest 中的重要字段public class AssetAddressCalculator { public string CalculateAddress(string assetPath, AssetBundleCollector collector) { if (collector.AddressRule EAddressRule.StringAddress) { return CalculateStringAddress(assetPath, collector); } else if (collector.AddressRule EAddressRule.GUIDAddress) { return AssetDatabase.AssetPathToGUID(assetPath); } else if (collector.AddressRule EAddressRule.LabelAddress) { return string.Join(,, collector.AssetTags); } return string.Empty; } private string CalculateStringAddress(string assetPath, AssetBundleCollector collector) { if (!string.IsNullOrEmpty(collector.Address)) { return collector.Address / Path.GetFileNameWithoutExtension(assetPath); } string relativePath assetPath.Substring(collector.CollectPath.Length); return relativePath.Replace(\\, /).TrimStart(/).Replace(Path.GetExtension(assetPath), ); } }String Address 计算详解使用 Collector 的 Address 作为前缀加上文件名生成地址。GUID Address 计算详解使用 Unity 的 AssetPathToGUID API 获取资源的 GUID。Label Address 计算详解使用 Collector 的 AssetTags 作为地址。四、BuildReport 概述4.1 BuildReport 的作用BuildReport 记录了构建的详细信息构建结果成功/失败构建参数构建时间资源统计Bundle 统计错误和警告4.2 BuildReport 的核心字段[Serializable] public class BuildReport { public string PackageName; public string PackageVersion; public bool BuildSuccess; public string BuildError; public long BuildStartTime; public long BuildEndTime; public long BuildDuration; public string BuildEngineVersion; public BuildTarget BuildTarget; public int TotalAssetCount; public int TotalBundleCount; public long TotalFileSize; public ListBuildBundleReport BundleReports new ListBuildBundleReport(); public Liststring Warnings new Liststring(); } [Serializable] public class BuildBundleReport { public string BundleName; public string FileName; public int AssetCount; public long FileSize; public string FileHash; public Liststring Assets new Liststring(); public Liststring Dependencies new Liststring(); }BuildSuccess 详解BuildSuccess 标识构建是否成功。BuildError 详解BuildError 记录构建失败的错误信息。BuildDuration 详解BuildDuration 记录构建耗时。BundleReports 详解BundleReports 包含了所有 Bundle 的报告。Warnings 详解Warnings 记录了构建过程中的警告信息。4.3 BuildReport 的生成public class BuildReportGenerator { public BuildReport Generate(BuildContext context) { BuildReport report new BuildReport(); // 1. 填充基本信息 report.PackageName context.Parameters.PackageName; report.PackageVersion context.Parameters.PackageVersion; report.BuildStartTime context.BuildStartTime; report.BuildEndTime DateTimeOffset.UtcNow.ToUnixTimeSeconds(); report.BuildDuration report.BuildEndTime - report.BuildStartTime; report.BuildEngineVersion Application.unityVersion; report.BuildTarget context.BuildTarget; // 2. 统计资源 foreach (var bundle in context.BuildMap.Bundles) { var bundleReport new BuildBundleReport(); bundleReport.BundleName bundle.BundleName; bundleReport.FileName bundle.FileName; bundleReport.AssetCount bundle.Assets.Count; bundleReport.FileSize bundle.FileSize; bundleReport.FileHash bundle.Hash; bundleReport.Assets bundle.Assets; bundleReport.Dependencies bundle.Dependencies; report.BundleReports.Add(bundleReport); } // 3. 计算总数 report.TotalBundleCount report.BundleReports.Count; report.TotalAssetCount report.BundleReports.Sum(b b.AssetCount); report.TotalFileSize report.BundleReports.Sum(b b.FileSize); // 4. 设置构建结果 report.BuildSuccess context.BuildSuccess; report.BuildError context.BuildError; report.Warnings context.Warnings; return report; } }填充基本信息详解填充 BuildReport 的基本信息包括包名、版本、构建时间、构建平台等。统计 Bundle 信息详解为每个 Bundle 生成 BuildBundleReport包含 Bundle 的详细信息。计算总数详解计算所有 Bundle 的资源总数、文件总大小等。设置构建结果详解设置构建的成功状态、错误信息、警告信息。4.4 BuildReport 的展示BuildReport 提供了多种展示方式Editor 内显示[CustomEditor(typeof(BuildReport))] public class BuildReportEditor : Editor { public override void OnInspectorGUI() { // 显示 BuildReport 的内容 } }导出为 JSONpublic void SaveToJson(string filePath) { string json JsonUtility.ToJson(this, true); File.WriteAllText(filePath, json); }导出为 HTML可以自定义将 BuildReport 导出为 HTML 格式便于在浏览器中查看。五、版本管理5.1 版本号格式YooAsset 使用语义化版本号Semantic Versioning格式Major.Minor.Patch如1.0.0Major 版本主版本号表示重大更新可能不兼容旧版本。Minor 版本次版本号表示新增功能向后兼容。Patch 版本补丁版本号表示 bug 修复。5.2 版本管理实现public class VersionManager { public bool IsNewerVersion(string newVersion, string oldVersion) { var newVer new Version(newVersion); var oldVer new Version(oldVersion); return newVer oldVer; } public string GenerateNextVersion(string currentVersion, EVersionIncrementType incrementType) { var ver new Version(currentVersion); switch (incrementType) { case EVersionIncrementType.Major: return ${ver.Major 1}.0.0; case EVersionIncrementType.Minor: return ${ver.Major}.{ver.Minor 1}.0; case EVersionIncrementType.Patch: return ${ver.Major}.{ver.Minor}.{ver.Build 1}; default: return currentVersion; } } }版本比较详解使用 .NET 的 Version 类进行版本比较。版本递增详解支持 Major、Minor、Patch 三种递增方式。5.3 版本号的使用版本号在 YooAsset 中有以下用途标识 Package 的版本标识构建产物的版本标识热更新的差异标识缓存的版本六、总结本章深入解析了 YooAsset 清单Manifest与报告Report的源码实现包括PackageManifest 概述PackageManifest 的作用、字段、序列化PackageManifest 生成流程生成流程、BuildTaskCreateManifest、地址计算BuildReport 概述BuildReport 的作用、字段、生成BuildReport 展示Editor 内显示、JSON 导出、HTML 导出版本管理版本号格式、版本比较、版本递增PackageManifest 和 BuildReport 是 YooAsset 编辑器端的重要组成部分深入理解它们的实现有助于更好地使用和扩展 YooAsset。上一篇构建管线分析下一篇调试与诊断工具