diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs index ce1b65a..a325d5c 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/AssetBundleSimulateBuilder.cs @@ -23,7 +23,7 @@ namespace YooAsset.Editor var buildResult = builder.Run(buildParameters); if (buildResult.Success) { - string manifestFileName = YooAssetSettingsData.GetPatchManifestFileName(buildParameters.PackageName, buildParameters.PackageVersion); + string manifestFileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion); string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}"; return manifestFilePath; } diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildBundleInfo.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildBundleInfo.cs index 1ec57f9..9663de4 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildBundleInfo.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildBundleInfo.cs @@ -182,13 +182,14 @@ namespace YooAsset.Editor /// internal PatchBundle CreatePatchBundle() { - string fileHash = PatchInfo.PatchFileHash; - string fileCRC = PatchInfo.PatchFileCRC; - long fileSize = PatchInfo.PatchFileSize; - bool isRawFile = IsRawFile; - byte loadMethod = (byte)LoadMethod; - string[] tags = GetBundleTags(); - PatchBundle patchBundle = new PatchBundle(BundleName, fileHash, fileCRC, fileSize, isRawFile, loadMethod, tags); + PatchBundle patchBundle = new PatchBundle(); + patchBundle.BundleName = BundleName; + patchBundle.FileHash = PatchInfo.PatchFileHash; + patchBundle.FileCRC = PatchInfo.PatchFileCRC; + patchBundle.FileSize = PatchInfo.PatchFileSize; + patchBundle.IsRawFile = IsRawFile; + patchBundle.LoadMethod = (byte)LoadMethod; + patchBundle.Tags = GetBundleTags(); return patchBundle; } } diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCopyBuildinFiles.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCopyBuildinFiles.cs index bd4c700..433b62c 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCopyBuildinFiles.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCopyBuildinFiles.cs @@ -45,7 +45,7 @@ namespace YooAsset.Editor // 拷贝补丁清单文件 { - string fileName = YooAssetSettingsData.GetPatchManifestFileName(buildPackageName, buildPackageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(buildPackageName, buildPackageVersion); string sourcePath = $"{packageOutputDirectory}/{fileName}"; string destPath = $"{streamingAssetsDirectory}/{fileName}"; EditorTools.CopyFile(sourcePath, destPath, true); diff --git a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCreatePatchManifest.cs b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCreatePatchManifest.cs index b5516e1..4dbb2c6 100644 --- a/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCreatePatchManifest.cs +++ b/Assets/YooAsset/Editor/AssetBundleBuilder/BuildTasks/TaskCreatePatchManifest.cs @@ -51,18 +51,26 @@ namespace YooAsset.Editor } } - // 创建补丁清单文件 + // 创建补丁清单文本文件 + { + string fileName = YooAssetSettingsData.GetPatchManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion); + string filePath = $"{packageOutputDirectory}/{fileName}"; + PatchManifest.SerializeToJson(filePath, patchManifest); + BuildRunner.Log($"创建补丁清单文件:{filePath}"); + } + + // 创建补丁清单二进制文件 string packageHash; { - string fileName = YooAssetSettingsData.GetPatchManifestFileName(buildParameters.PackageName, buildParameters.PackageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion); string filePath = $"{packageOutputDirectory}/{fileName}"; - PatchManifest.Serialize(filePath, patchManifest); + PatchManifest.SerializeToBinary(filePath, patchManifest); packageHash = HashUtility.FileMD5(filePath); BuildRunner.Log($"创建补丁清单文件:{filePath}"); - var patchManifestContext = new PatchManifestContext(); - string jsonData = FileUtility.ReadFile(filePath); - patchManifestContext.Manifest = PatchManifest.Deserialize(jsonData); + PatchManifestContext patchManifestContext = new PatchManifestContext(); + byte[] bytesData = FileUtility.ReadAllBytes(filePath); + patchManifestContext.Manifest = PatchManifest.DeserializeFromBinary(bytesData); context.SetContextObject(patchManifestContext); } diff --git a/Assets/YooAsset/Editor/AssetBundleReporter/AssetBundleReporterWindow.cs b/Assets/YooAsset/Editor/AssetBundleReporter/AssetBundleReporterWindow.cs index d084242..5cc2dd4 100644 --- a/Assets/YooAsset/Editor/AssetBundleReporter/AssetBundleReporterWindow.cs +++ b/Assets/YooAsset/Editor/AssetBundleReporter/AssetBundleReporterWindow.cs @@ -109,7 +109,7 @@ namespace YooAsset.Editor return; _reportFilePath = selectFilePath; - string jsonData = FileUtility.ReadFile(_reportFilePath); + string jsonData = FileUtility.ReadAllText(_reportFilePath); _buildReport = BuildReport.Deserialize(jsonData); _assetListViewer.FillViewData(_buildReport, _searchKeyWord); _bundleListViewer.FillViewData(_buildReport, _reportFilePath, _searchKeyWord); diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/DownloadPackageOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/DownloadPackageOperation.cs index 41e2a56..5cfe82b 100644 --- a/Assets/YooAsset/Runtime/PatchSystem/Operations/DownloadPackageOperation.cs +++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/DownloadPackageOperation.cs @@ -105,7 +105,7 @@ namespace YooAsset if (_steps == ESteps.LoadWebManifest) { - string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(_packageName, _packageVersion); string webURL = GetPatchManifestRequestURL(fileName); YooLogger.Log($"Beginning to request patch manifest : {webURL}"); _downloader = new UnityWebDataRequester(); @@ -131,7 +131,8 @@ namespace YooAsset // 解析补丁清单 try { - _remotePatchManifest = PatchManifest.Deserialize(_downloader.GetText()); + byte[] bytesData = _downloader.GetData(); + _remotePatchManifest = PatchManifest.DeserializeFromBinary(bytesData); _steps = ESteps.Done; Status = EOperationStatus.Succeed; } diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/InitializationOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/InitializationOperation.cs index 4ffdb53..58e4126 100644 --- a/Assets/YooAsset/Runtime/PatchSystem/Operations/InitializationOperation.cs +++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/InitializationOperation.cs @@ -56,8 +56,8 @@ namespace YooAsset try { YooLogger.Log($"Load simulation manifest file : {_simulatePatchManifestPath}"); - string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath); - var manifest = PatchManifest.Deserialize(jsonContent); + byte[] bytesData = FileUtility.ReadAllBytes(_simulatePatchManifestPath); + var manifest = PatchManifest.DeserializeFromBinary(bytesData); InitializedPackageVersion = manifest.PackageVersion; _impl.SetSimulatePatchManifest(manifest); _steps = ESteps.Done; @@ -491,7 +491,7 @@ namespace YooAsset if (_steps == ESteps.LoadAppManifest) { - string fileName = YooAssetSettingsData.GetPatchManifestFileName(_buildinPackageName, _buildinPackageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(_buildinPackageName, _buildinPackageVersion); string filePath = PathHelper.MakeStreamingLoadPath(fileName); string url = PathHelper.ConvertToWWWPath(filePath); _downloader = new UnityWebDataRequester(); @@ -513,7 +513,8 @@ namespace YooAsset // 解析APP里的补丁清单 try { - Manifest = PatchManifest.Deserialize(_downloader.GetText()); + byte[] bytesData = _downloader.GetData(); + Manifest = PatchManifest.DeserializeFromBinary(bytesData); } catch (System.Exception e) { @@ -590,7 +591,7 @@ namespace YooAsset if (_steps == ESteps.CopyAppManifest) { string savePath = PersistentHelper.GetCacheManifestFilePath(_buildinPackageName); - string fileName = YooAssetSettingsData.GetPatchManifestFileName(_buildinPackageName, _buildinPackageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(_buildinPackageName, _buildinPackageVersion); string filePath = PathHelper.MakeStreamingLoadPath(fileName); string url = PathHelper.ConvertToWWWPath(filePath); _downloader = new UnityWebFileRequester(); diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdatePackageManifestOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdatePackageManifestOperation.cs index b93c243..2c39b05 100644 --- a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdatePackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdatePackageManifestOperation.cs @@ -171,7 +171,7 @@ namespace YooAsset if (_steps == ESteps.LoadWebManifest) { - string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion); + string fileName = YooAssetSettingsData.GetPatchManifestBinaryFileName(_packageName, _packageVersion); string webURL = GetPatchManifestRequestURL(fileName); YooLogger.Log($"Beginning to request patch manifest : {webURL}"); _downloader2 = new UnityWebDataRequester(); @@ -194,8 +194,8 @@ namespace YooAsset { try { - string content = _downloader2.GetText(); - var manifest = PersistentHelper.SaveCacheManifestFile(_packageName, content); + byte[] bytesData = _downloader2.GetData(); + var manifest = PersistentHelper.SaveCacheManifestFile(_packageName, bytesData); _impl.SetLocalPatchManifest(manifest); FoundNewManifest = true; _steps = ESteps.InitVerifyingCache; diff --git a/Assets/YooAsset/Runtime/PatchSystem/PatchBundle.cs b/Assets/YooAsset/Runtime/PatchSystem/PatchBundle.cs index 5a1db90..45aaee1 100644 --- a/Assets/YooAsset/Runtime/PatchSystem/PatchBundle.cs +++ b/Assets/YooAsset/Runtime/PatchSystem/PatchBundle.cs @@ -109,15 +109,8 @@ namespace YooAsset } - public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, bool isRawFile, byte loadMethod, string[] tags) + public PatchBundle() { - BundleName = bundleName; - FileHash = fileHash; - FileCRC = fileCRC; - FileSize = fileSize; - IsRawFile = isRawFile; - LoadMethod = loadMethod; - Tags = tags; } /// diff --git a/Assets/YooAsset/Runtime/PatchSystem/PatchManifest.cs b/Assets/YooAsset/Runtime/PatchSystem/PatchManifest.cs index 8f25b97..dae56dd 100644 --- a/Assets/YooAsset/Runtime/PatchSystem/PatchManifest.cs +++ b/Assets/YooAsset/Runtime/PatchSystem/PatchManifest.cs @@ -266,48 +266,147 @@ namespace YooAsset /// - /// 序列化 + /// 序列化(JSON文件) /// - public static void Serialize(string savePath, PatchManifest patchManifest) + public static void SerializeToJson(string savePath, PatchManifest manifest) { - string json = JsonUtility.ToJson(patchManifest); + string json = JsonUtility.ToJson(manifest, true); FileUtility.CreateFile(savePath, json); } /// - /// 反序列化 + /// 序列化(二进制文件) /// - public static PatchManifest Deserialize(string jsonData) + public static void SerializeToBinary(string savePath, PatchManifest patchManifest) { - PatchManifest patchManifest = JsonUtility.FromJson(jsonData); - if (patchManifest == null) - throw new System.Exception($"{nameof(PatchManifest)} deserialize object is null !"); + using (FileStream fs = new FileStream(savePath, FileMode.Create)) + { + // 创建缓存器 + BufferWriter buffer = new BufferWriter(YooAssetSettings.PatchManifestFileMaxSize); - // 检测文件版本 - if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion) - throw new Exception($"The manifest file version are not compatible : {patchManifest.FileVersion} != {YooAssetSettings.PatchManifestFileVersion}"); + // 写入文件标记 + buffer.WriteUInt32(YooAssetSettings.PatchManifestFileSign); + + // 写入文件版本 + buffer.WriteUTF8(patchManifest.FileVersion); + + // 写入文件头信息 + buffer.WriteBool(patchManifest.EnableAddressable); + buffer.WriteInt32(patchManifest.OutputNameStyle); + buffer.WriteUTF8(patchManifest.PackageName); + buffer.WriteUTF8(patchManifest.PackageVersion); + + // 写入资源列表 + buffer.WriteInt32(patchManifest.AssetList.Count); + for (int i = 0; i < patchManifest.AssetList.Count; i++) + { + var patchAsset = patchManifest.AssetList[i]; + buffer.WriteUTF8(patchAsset.Address); + buffer.WriteUTF8(patchAsset.AssetPath); + buffer.WriteUTF8Array(patchAsset.AssetTags); + buffer.WriteInt32(patchAsset.BundleID); + buffer.WriteInt32Array(patchAsset.DependIDs); + } + + // 写入资源包列表 + buffer.WriteInt32(patchManifest.BundleList.Count); + for (int i = 0; i < patchManifest.BundleList.Count; i++) + { + var patchBundle = patchManifest.BundleList[i]; + buffer.WriteUTF8(patchBundle.BundleName); + buffer.WriteUTF8(patchBundle.FileHash); + buffer.WriteUTF8(patchBundle.FileCRC); + buffer.WriteInt64(patchBundle.FileSize); + buffer.WriteBool(patchBundle.IsRawFile); + buffer.WriteByte(patchBundle.LoadMethod); + buffer.WriteUTF8Array(patchBundle.Tags); + } + + // 写入文件流 + buffer.WriteToStream(fs); + fs.Flush(); + } + } + + /// + /// 反序列化(二进制文件) + /// + public static PatchManifest DeserializeFromBinary(byte[] binaryData) + { + // 创建缓存器 + BufferReader buffer = new BufferReader(binaryData); + + // 读取文件标记 + uint fileSign = buffer.ReadUInt32(); + if (fileSign != YooAssetSettings.PatchManifestFileSign) + throw new Exception("Invalid manifest file !"); + + PatchManifest manifest = new PatchManifest(); + { + // 读取文件版本 + manifest.FileVersion = buffer.ReadUTF8(); + if (manifest.FileVersion != YooAssetSettings.PatchManifestFileVersion) + throw new Exception($"The manifest file version are not compatible : {manifest.FileVersion} != {YooAssetSettings.PatchManifestFileVersion}"); + + // 读取文件头信息 + manifest.EnableAddressable = buffer.ReadBool(); + manifest.OutputNameStyle = buffer.ReadInt32(); + manifest.PackageName = buffer.ReadUTF8(); + manifest.PackageVersion = buffer.ReadUTF8(); + + // 读取资源列表 + int patchAssetCount = buffer.ReadInt32(); + manifest.AssetList = new List(patchAssetCount); + for (int i = 0; i < patchAssetCount; i++) + { + var patchAsset = new PatchAsset(); + patchAsset.Address = buffer.ReadUTF8(); + patchAsset.AssetPath = buffer.ReadUTF8(); + patchAsset.AssetTags = buffer.ReadUTF8Array(); + patchAsset.BundleID = buffer.ReadInt32(); + patchAsset.DependIDs = buffer.ReadInt32Array(); + manifest.AssetList.Add(patchAsset); + } + + // 读取资源包列表 + int patchBundleCount = buffer.ReadInt32(); + manifest.BundleList = new List(patchBundleCount); + for (int i = 0; i < patchBundleCount; i++) + { + var patchBundle = new PatchBundle(); + patchBundle.BundleName = buffer.ReadUTF8(); + patchBundle.FileHash = buffer.ReadUTF8(); + patchBundle.FileCRC = buffer.ReadUTF8(); + patchBundle.FileSize = buffer.ReadInt64(); + patchBundle.IsRawFile = buffer.ReadBool(); + patchBundle.LoadMethod = buffer.ReadByte(); + patchBundle.Tags = buffer.ReadUTF8Array(); + manifest.BundleList.Add(patchBundle); + } + } // BundleList - foreach (var patchBundle in patchManifest.BundleList) + foreach (var patchBundle in manifest.BundleList) { - patchBundle.ParseBundle(patchManifest.PackageName, patchManifest.OutputNameStyle); - patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle); + patchBundle.ParseBundle(manifest.PackageName, manifest.OutputNameStyle); + manifest.BundleDic.Add(patchBundle.BundleName, patchBundle); } // AssetList - foreach (var patchAsset in patchManifest.AssetList) + foreach (var patchAsset in manifest.AssetList) { // 注意:我们不允许原始路径存在重名 string assetPath = patchAsset.AssetPath; - if (patchManifest.AssetDic.ContainsKey(assetPath)) + if (manifest.AssetDic.ContainsKey(assetPath)) throw new Exception($"AssetPath have existed : {assetPath}"); else - patchManifest.AssetDic.Add(assetPath, patchAsset); + manifest.AssetDic.Add(assetPath, patchAsset); } - return patchManifest; + return manifest; } + /// /// 生成Bundle文件的正式名称 /// diff --git a/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs b/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs index c0f5d0c..5411e1b 100644 --- a/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs +++ b/Assets/YooAsset/Runtime/Settings/YooAssetSettings.cs @@ -16,13 +16,23 @@ namespace YooAsset public string RawFileVariant = "rawfile"; /// - /// 补丁清单文件名称 + /// 清单文件名称 /// public string PatchManifestFileName = "PatchManifest"; /// - /// 补丁清单文件格式版本 + /// 清单文件头标记 + /// + public const uint PatchManifestFileSign = 0x594F4F; + + /// + /// 清单文件极限大小(100MB) + /// + public const int PatchManifestFileMaxSize = 104857600; + + /// + /// 清单文件格式版本 /// public const string PatchManifestFileVersion = "1.3.4"; diff --git a/Assets/YooAsset/Runtime/Settings/YooAssetSettingsData.cs b/Assets/YooAsset/Runtime/Settings/YooAssetSettingsData.cs index 5414dee..7a38d1d 100644 --- a/Assets/YooAsset/Runtime/Settings/YooAssetSettingsData.cs +++ b/Assets/YooAsset/Runtime/Settings/YooAssetSettingsData.cs @@ -51,11 +51,19 @@ namespace YooAsset /// /// 获取补丁清单文件完整名称 /// - public static string GetPatchManifestFileName(string packageName, string packageVersion) + public static string GetPatchManifestBinaryFileName(string packageName, string packageVersion) { return $"{Setting.PatchManifestFileName}_{packageName}_{packageVersion}.bytes"; } + /// + /// 获取补丁清单文件完整名称 + /// + public static string GetPatchManifestJsonFileName(string packageName, string packageVersion) + { + return $"{Setting.PatchManifestFileName}_{packageName}_{packageVersion}.json"; + } + /// /// 获取补丁清单哈希文件完整名称 /// diff --git a/Assets/YooAsset/Runtime/Utility/YooHelper.cs b/Assets/YooAsset/Runtime/Utility/YooHelper.cs index dadc15e..4c53320 100644 --- a/Assets/YooAsset/Runtime/Utility/YooHelper.cs +++ b/Assets/YooAsset/Runtime/Utility/YooHelper.cs @@ -128,19 +128,19 @@ namespace YooAsset { YooLogger.Log($"Load sandbox patch manifest file : {packageName}"); string filePath = GetCacheManifestFilePath(packageName); - string jsonData = File.ReadAllText(filePath); - return PatchManifest.Deserialize(jsonData); + byte[] bytesData = File.ReadAllBytes(filePath); + return PatchManifest.DeserializeFromBinary(bytesData); } /// /// 存储沙盒内清单文件 /// - public static PatchManifest SaveCacheManifestFile(string packageName, string fileContent) + public static PatchManifest SaveCacheManifestFile(string packageName, byte[] fileBytesData) { YooLogger.Log($"Save sandbox patch manifest file : {packageName}"); - var manifest = PatchManifest.Deserialize(fileContent); + var manifest = PatchManifest.DeserializeFromBinary(fileBytesData); string savePath = GetCacheManifestFilePath(packageName); - FileUtility.CreateFile(savePath, fileContent); + FileUtility.CreateFile(savePath, fileBytesData); return manifest; } diff --git a/Assets/YooAsset/Runtime/Utility/YooUtility.cs b/Assets/YooAsset/Runtime/Utility/YooUtility.cs index 9e118ab..36e5a7d 100644 --- a/Assets/YooAsset/Runtime/Utility/YooUtility.cs +++ b/Assets/YooAsset/Runtime/Utility/YooUtility.cs @@ -117,15 +117,25 @@ namespace YooAsset internal static class FileUtility { /// - /// 读取文件 + /// 读取文件的文本数据 /// - public static string ReadFile(string filePath) + public static string ReadAllText(string filePath) { if (File.Exists(filePath) == false) return string.Empty; return File.ReadAllText(filePath, Encoding.UTF8); } + /// + /// 读取文件的字节数据 + /// + public static byte[] ReadAllBytes(string filePath) + { + if (File.Exists(filePath) == false) + return null; + return File.ReadAllBytes(filePath); + } + /// /// 创建文件(如果已经存在则删除旧文件) ///