public static ZipArchiveManifest BuildZipArchives(string outputPath, BundleBuilderData.BundleInfo[] builds, BuildTarget targetPlatform) { var manifest = new ZipArchiveManifest(); foreach (var bundle in builds) { var archiveEntry = new ZipArchiveEntry() { name = bundle.name, }; manifest.archives.Add(archiveEntry); var filename = Path.Combine(outputPath, bundle.name); using (var zip = new ZipOutputStream(File.OpenWrite(filename))) { zip.IsStreamOwner = true; foreach (var split in bundle.splits) { foreach (var asset in split.assets) { BuildZipArchiveObject(zip, asset, archiveEntry); } } zip.Close(); } } return(manifest); }
//TODO: zip 打包拆包 public static ZipArchiveManifest BuildZipArchives(PackageBuildInfo buildInfo, List <ZipArchiveBuild> builds) { var manifest = new ZipArchiveManifest(); foreach (var build in builds) { var entry = new ZipArchiveManifestEntry() { name = build.name, }; manifest.archives.Add(entry); var zipArchiveFileName = Path.Combine(buildInfo.zipArchivePath, entry.name); if (File.Exists(zipArchiveFileName)) { File.Delete(zipArchiveFileName); } using (var zip = new ZipOutputStream(File.Open(zipArchiveFileName, FileMode.Create, FileAccess.Write, FileShare.Write))) { zip.IsStreamOwner = true; foreach (var assetPath in build.assetPaths) { BuildZipArchiveObject(zip, assetPath, entry); } } } return(manifest); }
private static void Cleanup(PackageBuildInfo buildInfo, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest, FileListManifest fileListManifest, RawFileManifest rawFileManifest, EmbeddedManifest embeddedManifest) { foreach (var dir in Directory.GetDirectories(buildInfo.packagePath)) { CleanupRecursively(dir, "Assets", fileListManifest, false); } foreach (var file in Directory.GetFiles(buildInfo.packagePath)) { var match = false; var fi = new FileInfo(file); var filename = fi.Name; if (builtinFiles.Contains(filename)) { match = true; } if (!match && buildInfo.filelist.Contains(filename)) { match = true; } if (!match && filename == Manifest.EmbeddedManifestFileName && embeddedManifest.bundles.Count > 0) { match = true; } if (!match) { Debug.LogWarning("delete unused file: " + filename); try { fi.Delete(); } catch (Exception exception) { Debug.LogError(exception); } } } }
// 生成打包 private static void _BuildPackages(PackageBuildInfo packageBuildInfo) { Debug.Log($"building bundles..."); Scan(packageBuildInfo.data); var assetBundleBuilds = GenerateAssetBundleBuilds(packageBuildInfo); var zipArchiveBuilds = GenerateZipArchiveBuilds(packageBuildInfo); var fileListBuilds = GenerateFileListBuilds(packageBuildInfo); var rawFileBuilds = GenerateRawFileBuilds(packageBuildInfo); AssetBundleManifest assetBundleManifest = null; ZipArchiveManifest zipArchiveManifest = null; FileListManifest fileListManifest = null; RawFileManifest rawFileManifest = null; if (assetBundleBuilds.Length != 0) { assetBundleManifest = BuildAssetBundles(packageBuildInfo, assetBundleBuilds); } if (zipArchiveBuilds.Count != 0) { zipArchiveManifest = BuildZipArchives(packageBuildInfo, zipArchiveBuilds); } if (fileListBuilds.Length != 0) { fileListManifest = BuildFileLists(packageBuildInfo, fileListBuilds); } if (rawFileBuilds.Length != 0) { rawFileManifest = BuildRawFiles(packageBuildInfo, rawFileBuilds); } var embeddedManifest = BuildFinalPackages(packageBuildInfo, assetBundleManifest, zipArchiveManifest, fileListManifest, rawFileManifest); Cleanup(packageBuildInfo, assetBundleManifest, zipArchiveManifest, fileListManifest, rawFileManifest, embeddedManifest); packageBuildInfo.DoAnalyze(); packageBuildInfo.data.build++; packageBuildInfo.data.MarkAsDirty(); Debug.Log( $"{packageBuildInfo.packagePath}: build bundles finished. {assetBundleBuilds.Length} assetbundles. {zipArchiveBuilds.Count} zip archives. {fileListBuilds.Length} file lists. {embeddedManifest.bundles.Count} bundles to streamingassets."); }
// 生成打包 public static void Build(BundleBuilderData data, string outputPath, BuildTarget targetPlatform) { BundleBuilder.Scan(data, targetPlatform); var assetBundleBuilds = GenerateAssetBundleBuilds(data); var zipArchiveBuilds = GenerateZipArchiveBuilds(data); // var sceneBundleBuilds = GenerateSceneBundleBuilds(data); if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } AssetBundleManifest assetBundleManifest = null; ZipArchiveManifest zipArchiveManifest = null; // UnityEditor.Build.Reporting.BuildReport report = null; // if (sceneBundleBuilds.Length != 0) // { // Debug.Log($"build {sceneBundleBuilds.Length} scene bundles"); // var levels = new List<string>(sceneBundleBuilds.Length); // foreach (var build in sceneBundleBuilds) // { // levels.Add(build.scenePath); // } // report = BuildPipeline.BuildPlayer(levels.ToArray(), outputPath, targetPlatform, BuildOptions.BuildAdditionalStreamedScenes); // } if (assetBundleBuilds.Length != 0) { assetBundleManifest = BuildPipeline.BuildAssetBundles(outputPath, assetBundleBuilds, BuildAssetBundleOptions.None, targetPlatform); } if (zipArchiveBuilds.Length != 0) { zipArchiveManifest = BuildZipArchives(outputPath, zipArchiveBuilds, targetPlatform); } EmbeddedManifest embeddedManifest; BuildManifest(data, outputPath, assetBundleManifest, zipArchiveManifest, out embeddedManifest); PrepareStreamingAssets(data, outputPath, embeddedManifest); Cleanup(outputPath, assetBundleManifest, zipArchiveManifest, embeddedManifest); Debug.Log($"build bundles finished {DateTime.Now}. {assetBundleBuilds.Length} assetbundles. {zipArchiveBuilds.Length} zip archives. {embeddedManifest.bundles.Count} bundles to streamingassets."); }
// 生成清单 public static void BuildManifest(BundleBuilderData data, string outputPath, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest) { var manifest = new Manifest(); if (assetBundleManifest != null) { var assetBundles = assetBundleManifest.GetAllAssetBundles(); foreach (var assetBundle in assetBundles) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; if (TryGetBundleSplit(data, assetBundle, out bundleInfo, out bundleSplit)) { // Debug.Log(bundleInfo.name); var assetBundlePath = Path.Combine(outputPath, assetBundle); using (var stream = File.OpenRead(assetBundlePath)) { var fileInfo = new FileInfo(assetBundlePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.AssetBundle; bundle.name = bundleSplit.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.startup = bundleInfo.load == BundleLoad.Startup; bundle.priority = bundleInfo.priority; foreach (var asset in bundleSplit.assets) { var assetPath = AssetDatabase.GetAssetPath(asset); bundle.assets.Add(assetPath); } bundle.dependencies = assetBundleManifest.GetAllDependencies(assetBundle); manifest.bundles.Add(bundle); } } } } if (zipArchiveManifest != null) { foreach (var zipArchive in zipArchiveManifest.archives) { var bundleInfo = GetBundleInfo(data, zipArchive.name); var zipArchivePath = Path.Combine(outputPath, zipArchive.name); using (var stream = File.OpenRead(zipArchivePath)) { var fileInfo = new FileInfo(zipArchivePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.ZipArchive; bundle.name = zipArchive.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.startup = bundleInfo.load == BundleLoad.Startup; bundle.priority = bundleInfo.priority; foreach (var assetPath in zipArchive.assets) { // var assetPath = AssetDatabase.GetAssetPath(asset.target); bundle.assets.Add(assetPath); } // bundle.dependencies = null; manifest.bundles.Add(bundle); } } } if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } var json = JsonUtility.ToJson(manifest); var jsonChecksum = Utils.Crc16.ToString(Utils.Crc16.ComputeChecksum(System.Text.Encoding.UTF8.GetBytes(json))); var manifestPath = Path.Combine(outputPath, "manifest.json"); var manifestChecksumPath = Path.Combine(outputPath, "checksum.txt"); File.WriteAllText(manifestPath, json); File.WriteAllText(manifestChecksumPath, jsonChecksum); }
private static void Cleanup(string outputPath, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest) { foreach (var file in Directory.GetFiles(outputPath)) { var fi = new FileInfo(file); var match = false; if ( fi.Name == "AssetBundles" || fi.Name == "AssetBundles.manifest" || fi.Name == "checksum.txt" || fi.Name == "manifest.json" ) { match = true; } if (!match) { foreach (var assetBundle in assetBundleManifest.GetAllAssetBundles()) { if (fi.Name == assetBundle || fi.Name == assetBundle + ".manifest") { match = true; break; } } } if (!match) { foreach (var zipArchive in zipArchiveManifest.archives) { if (fi.Name == zipArchive.name) { match = true; break; } } } if (!match) { // Debug.LogWarning("delete unused file: " + fi.Name); try { fi.Delete(); } catch (Exception exception) { Debug.LogError(exception); } } } }
// 生成清单 public static void BuildManifest(BundleBuilderData data, string outputPath, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest, out EmbeddedManifest embeddedManifest) { var manifest = new Manifest(); embeddedManifest = new EmbeddedManifest(); if (assetBundleManifest != null) { var assetBundles = assetBundleManifest.GetAllAssetBundles(); foreach (var assetBundle in assetBundles) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; if (TryGetBundleSplit(data, assetBundle, out bundleInfo, out bundleSplit)) { // Debug.Log(bundleInfo.name); var assetBundlePath = Path.Combine(outputPath, assetBundle); using (var stream = File.OpenRead(assetBundlePath)) { var fileInfo = new FileInfo(assetBundlePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.AssetBundle; bundle.name = bundleSplit.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.load = bundleInfo.load; bundle.priority = bundleInfo.priority; foreach (var asset in bundleSplit.assets) { var assetPath = AssetDatabase.GetAssetPath(asset); bundle.assets.Add(assetPath); } bundle.dependencies = assetBundleManifest.GetAllDependencies(assetBundle); manifest.bundles.Add(bundle); if (bundleInfo.streamingAssets) { embeddedManifest.bundles.Add(new EmbeddedManifest.BundleInfo() { name = bundle.name, checksum = bundle.checksum, size = bundle.size, }); } } } } } if (zipArchiveManifest != null) { foreach (var zipArchive in zipArchiveManifest.archives) { var bundleInfo = GetBundleInfo(data, zipArchive.name); var zipArchivePath = Path.Combine(outputPath, zipArchive.name); using (var stream = File.OpenRead(zipArchivePath)) { var fileInfo = new FileInfo(zipArchivePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.ZipArchive; bundle.name = zipArchive.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.load = bundleInfo.load; bundle.priority = bundleInfo.priority; foreach (var assetPath in zipArchive.assets) { // var assetPath = AssetDatabase.GetAssetPath(asset.target); bundle.assets.Add(assetPath); } // bundle.dependencies = null; manifest.bundles.Add(bundle); if (bundleInfo.streamingAssets) { embeddedManifest.bundles.Add(new EmbeddedManifest.BundleInfo() { name = bundle.name, checksum = bundle.checksum, size = bundle.size, }); } } } } if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } OutputManifest(manifest, outputPath); OutputEmbeddedManifest(embeddedManifest, outputPath); }
// 生成最终包文件, 生成最终清单 public static EmbeddedManifest BuildFinalPackages(PackageBuildInfo buildInfo, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest, FileListManifest fileListManifest, RawFileManifest rawFileManifest) { var data = buildInfo.data; var manifest = new Manifest(); manifest.chunkSize = data.chunkSize; manifest.build = buildInfo.data.build; manifest.timestamp = (int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds; manifest.tag = buildInfo.sharedBuildInfo.tag; var embeddedManifest = new EmbeddedManifest(); if (assetBundleManifest != null) { var assetBundles = assetBundleManifest.GetAllAssetBundles(); foreach (var assetBundle in assetBundles) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; BundleBuilderData.BundleSlice bundleSlice; if (TryGetBundleSlice(data, assetBundle, out bundleInfo, out bundleSplit, out bundleSlice)) { // Debug.Log(bundleInfo.name); var fileEntry = EncryptFileEntry(data, buildInfo, bundleSplit.encrypted, bundleSlice.name, buildInfo.assetBundlePath); var bundle = new Manifest.BundleInfo(); bundle.comment = bundleInfo.note; bundle.tag = bundleInfo.tag; bundle.encrypted = bundleSplit.encrypted; bundle.rsize = fileEntry.rsize; bundle.type = Manifest.BundleType.AssetBundle; bundle.name = fileEntry.name; bundle.checksum = fileEntry.checksum; bundle.size = fileEntry.size; bundle.load = bundleInfo.load; bundle.priority = GetPriority(buildInfo, bundleInfo, bundleSlice); if (bundleSlice.lastBuildSize != fileEntry.size) { bundleSlice.lastBuildSize = fileEntry.size; data.MarkAsDirty(); } for (int assetIndex = 0, assetCount = bundleSlice.GetAssetCount(); assetIndex < assetCount; assetIndex++) { var assetPath = bundleSlice.GetAssetPath(assetIndex); bundle.assets.Add(assetPath); } bundle.dependencies = assetBundleManifest.GetAllDependencies(assetBundle); buildInfo.CreateEntry(bundle); manifest.bundles.Add(bundle); if (bundleSlice.streamingAssets || data.streamingAssetsAnyway) { embeddedManifest.bundles.Add(fileEntry); } } } } if (zipArchiveManifest != null) { foreach (var zipArchive in zipArchiveManifest.archives) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; BundleBuilderData.BundleSlice bundleSlice; if (TryGetBundleSlice(data, zipArchive.name, out bundleInfo, out bundleSplit, out bundleSlice)) { var fileEntry = EncryptFileEntry(data, buildInfo, bundleSplit.encrypted, zipArchive.name, buildInfo.zipArchivePath); var bundle = new Manifest.BundleInfo(); bundle.comment = bundleInfo.note; bundle.tag = bundleInfo.tag; bundle.encrypted = bundleSplit.encrypted; bundle.rsize = fileEntry.rsize; bundle.type = Manifest.BundleType.ZipArchive; bundle.name = fileEntry.name; bundle.checksum = fileEntry.checksum; bundle.size = fileEntry.size; bundle.load = bundleInfo.load; bundle.priority = GetPriority(buildInfo, bundleInfo, bundleSlice); foreach (var assetPath in zipArchive.assets) { bundle.assets.Add(assetPath); } manifest.bundles.Add(bundle); if (bundleSlice.streamingAssets || data.streamingAssetsAnyway) { embeddedManifest.bundles.Add(fileEntry); } } } } if (fileListManifest != null) { foreach (var fileList in fileListManifest.fileLists) { var bundleInfo = GetBundleInfo(data, fileList.name); var fileListPath = Path.Combine(buildInfo.packagePath, fileList.name); var fileEntry = GenFileEntry(fileList.name, fileListPath); var bundle = new Manifest.BundleInfo(); bundle.comment = bundleInfo.note; bundle.tag = bundleInfo.tag; bundle.type = Manifest.BundleType.FileList; bundle.name = fileList.name; bundle.checksum = fileEntry.checksum; bundle.size = fileEntry.size; bundle.load = bundleInfo.load; bundle.priority = bundleInfo.priority; buildInfo.filelist.Add(fileList.name); foreach (var bundleTargets in bundleInfo.targets) { var targetPath = bundleTargets.targetPath; bundle.assets.Add(targetPath); } manifest.bundles.Add(bundle); if (bundleInfo.streamingAssets || data.streamingAssetsAnyway) { embeddedManifest.bundles.Add(fileEntry); } } } WriteManifest(buildInfo, manifest); WriteEmbeddedManifest(buildInfo, embeddedManifest); if (buildInfo.buildTarget == EditorUserBuildSettings.activeBuildTarget) { BuildStreamingAssets(buildInfo, fileListManifest); } return(embeddedManifest); }