using System; using System.IO; using AlicizaX.Resource.Runtime; using UnityEditor; using UnityEditor.Build.Reporting; using UnityEngine; using YooAsset; using YooAsset.Editor; using BuildResult = UnityEditor.Build.Reporting.BuildResult; namespace BuildCli { /// /// 打包工具类。 /// 通过CommandLineReader可以不前台开启Unity实现静默打包以及CLI工作流,详见CommandLineReader.cs example1 /// public static class ReleaseTools { // public static void BuildDll() // { // string platform = CommandLineReader.GetCustomArgument("platform"); // if (string.IsNullOrEmpty(platform)) // { // Debug.LogError($"Build Asset Bundle Error!platform is null"); // return; // } // // BuildTarget target = GetBuildTarget(platform); // // BuildDLLCommand.BuildAndCopyDlls(target); // } // public static void BuildAssetBundle() // { // string outputRoot = CommandLineReader.GetCustomArgument("outputRoot"); // if (string.IsNullOrEmpty(outputRoot)) // { // Debug.LogError($"Build Asset Bundle Error!outputRoot is null"); // return; // } // // string packageVersion = CommandLineReader.GetCustomArgument("packageVersion"); // if (string.IsNullOrEmpty(packageVersion)) // { // Debug.LogError($"Build Asset Bundle Error!packageVersion is null"); // return; // } // // string platform = CommandLineReader.GetCustomArgument("platform"); // if (string.IsNullOrEmpty(platform)) // { // Debug.LogError($"Build Asset Bundle Error!platform is null"); // return; // } // // BuildTarget target = GetBuildTarget(platform); // BuildInternal(target, outputRoot); // Debug.LogWarning($"Start BuildPackage BuildTarget:{target} outputPath:{outputRoot}"); // } // [MenuItem("AlicizaFramework/Quick Build/一键打包AssetBundle")] public static void BuildCurrentPlatformAB() { BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildInternal(target, Application.dataPath + "/../Builds/", packageVersion: GetBuildPackageVersion()); AssetDatabase.Refresh(); } private static BuildTarget GetBuildTarget(string platform) { BuildTarget target = BuildTarget.NoTarget; switch (platform) { case "Android": target = BuildTarget.Android; break; case "IOS": target = BuildTarget.iOS; break; case "Windows": target = BuildTarget.StandaloneWindows64; break; case "MacOS": target = BuildTarget.StandaloneOSX; break; case "Linux": target = BuildTarget.StandaloneLinux64; break; case "WebGL": target = BuildTarget.WebGL; break; case "Switch": target = BuildTarget.Switch; break; case "PS4": target = BuildTarget.PS4; break; case "PS5": target = BuildTarget.PS5; break; } return target; } private static void BuildInternal(BuildTarget buildTarget, string outputRoot, string packageVersion = "1.0", EBuildPipeline buildPipeline = EBuildPipeline.ScriptableBuildPipeline) { Debug.Log($"开始构建 : {buildTarget}"); IBuildPipeline pipeline = null; BuildParameters buildParameters = null; if (buildPipeline == EBuildPipeline.BuiltinBuildPipeline) { // 构建参数 BuiltinBuildParameters builtinBuildParameters = new BuiltinBuildParameters(); // 执行构建 pipeline = new BuiltinBuildPipeline(); buildParameters = builtinBuildParameters; builtinBuildParameters.CompressOption = ECompressOption.LZ4; } else { ScriptableBuildParameters scriptableBuildParameters = new ScriptableBuildParameters(); // 执行构建 pipeline = new ScriptableBuildPipeline(); buildParameters = scriptableBuildParameters; scriptableBuildParameters.CompressOption = ECompressOption.LZ4; } buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot(); buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot(); buildParameters.BuildPipeline = buildPipeline.ToString(); buildParameters.BuildTarget = buildTarget; buildParameters.BuildMode = EBuildMode.IncrementalBuild; buildParameters.PackageName = "DefaultPackage"; buildParameters.PackageVersion = packageVersion; buildParameters.VerifyBuildingResult = true; buildParameters.FileNameStyle = EFileNameStyle.BundleName_HashName; buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.ClearAndCopyAll; buildParameters.BuildinFileCopyParams = string.Empty; buildParameters.EncryptionServices = CreateEncryptionInstance("DefaultPackage", buildPipeline); // 启用共享资源打包 buildParameters.EnableSharePackRule = true; var buildResult = pipeline.Run(buildParameters, true); if (buildResult.Success) { Debug.Log($"构建成功 : {buildResult.OutputPackageDirectory}"); } else { Debug.LogError($"构建失败 : {buildResult.ErrorInfo}"); } } [MenuItem("开发工具/Build/Build Test")] public static void BuildAAA() { string outPath = System.IO.Path.Combine(Application.dataPath, "../../bundles/"); var bundlePath = Application.dataPath + "/../Bundles/Windows"; if (Directory.Exists(bundlePath)) { Directory.Delete(bundlePath, true); } if (Directory.Exists(outPath + "bundles")) { Directory.Delete(outPath + "bundles", true); } int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute; string version = DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes; BuildTest(outPath, version); BuildUpdateData(version); } static void BuildUpdateData(string version) { string outPath = System.IO.Path.Combine(Application.dataPath, "../../bundles/"); ResourcePatchData updateData = new ResourcePatchData() { Version = Application.version, BundleUrl = $"http://127.0.0.1:8081/res/{version}/", Notice = "Test Notice", }; File.WriteAllText(Path.Combine(outPath, "UpdateData.json"), Newtonsoft.Json.JsonConvert.SerializeObject(updateData)); } public static void BuildTest(string outputRoot, string version) { Debug.Log($"开始构建 : {BuildTarget.StandaloneWindows64}"); IBuildPipeline pipeline = null; BuildParameters buildParameters = null; ScriptableBuildParameters scriptableBuildParameters = new ScriptableBuildParameters(); // 执行构建 pipeline = new ScriptableBuildPipeline(); buildParameters = scriptableBuildParameters; scriptableBuildParameters.CompressOption = ECompressOption.LZ4; buildParameters.BuildOutputRoot = Application.dataPath + "/../Bundles/Windows"; buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot(); buildParameters.BuildPipeline = EBuildPipeline.ScriptableBuildPipeline.ToString(); buildParameters.BuildTarget = BuildTarget.StandaloneWindows64; buildParameters.BuildMode = EBuildMode.IncrementalBuild; buildParameters.PackageName = "DefaultPackage"; buildParameters.PackageVersion = version; buildParameters.VerifyBuildingResult = true; buildParameters.FileNameStyle = EFileNameStyle.BundleName_HashName; buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.ClearAndCopyByTags; buildParameters.BuildinFileCopyParams = "Launch"; buildParameters.EncryptionServices = CreateEncryptionInstance("DefaultPackage", EBuildPipeline.ScriptableBuildPipeline); // 启用共享资源打包 buildParameters.EnableSharePackRule = true; var buildResult = pipeline.Run(buildParameters, true); if (buildResult.Success) { var bundlePath = Application.dataPath + $"/../Bundles/Windows/StandaloneWindows64/DefaultPackage/{version}/"; var targetPath = System.IO.Path.Combine(Application.dataPath, $"../../bundles/res/{version}"); if (!Directory.Exists(targetPath)) { Directory.CreateDirectory(targetPath); } DeleteFilesInDirectory(targetPath); CopyFiles(bundlePath, targetPath); Debug.Log($"构建成功 : {buildResult.OutputPackageDirectory}"); } else { Debug.LogError($"构建失败 : {buildResult.ErrorInfo}"); } } static void CopyFiles(string sourceDirectory, string destinationDirectory) { // 确保目标目录存在 if (!Directory.Exists(destinationDirectory)) { Directory.CreateDirectory(destinationDirectory); } // 获取源目录下的所有文件 string[] files = Directory.GetFiles(sourceDirectory); foreach (string filePath in files) { // 构建目标文件路径 string fileName = Path.GetFileName(filePath); string destinationFilePath = Path.Combine(destinationDirectory, fileName); // 拷贝文件 File.Copy(filePath, destinationFilePath, true); // 如果目标文件已存在,覆盖 } } static void DeleteFilesInDirectory(string directoryPath) { // 获取目录下的所有文件 string[] files = Directory.GetFiles(directoryPath); foreach (string filePath in files) { // 删除文件 File.Delete(filePath); } } /// /// 创建加密类实例 /// private static IEncryptionServices CreateEncryptionInstance(string packageName, EBuildPipeline buildPipeline) { var encryptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(packageName, buildPipeline); var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices)); Debug.Log("encryptionClassName:" + encryptionClassName); foreach (var k in encryptionClassTypes) { Debug.Log(k.FullName); } var classType = encryptionClassTypes.Find(x => x.FullName != null && x.FullName.Equals(encryptionClassName)); if (classType != null) { Debug.Log($"Use Encryption {classType}"); return (IEncryptionServices)Activator.CreateInstance(classType); } else { return null; } } // [MenuItem("AlicizaFramework/Quick Build/一键打包Window", false, 90)] public static void AutomationBuild() { BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildDLLCommand.BuildAndCopyDlls(target); AssetDatabase.Refresh(); BuildInternal(target, Application.dataPath + "/../Builds/Windows", packageVersion: GetBuildPackageVersion()); AssetDatabase.Refresh(); BuildImp(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64, $"{Application.dataPath}/../Builds/Windows/Release_Windows.exe"); } // 构建版本相关 private static string GetBuildPackageVersion() { int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute; return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes; } // [MenuItem("AlicizaFramework/Quick Build/一键打包Android", false, 90)] public static void AutomationBuildAndroid() { BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildDLLCommand.BuildAndCopyDlls(target); AssetDatabase.Refresh(); BuildInternal(target, outputRoot: Application.dataPath + "/../Bundles", packageVersion: GetBuildPackageVersion()); AssetDatabase.Refresh(); BuildImp(BuildTargetGroup.Android, BuildTarget.Android, $"{Application.dataPath}/../Build/Android/{GetBuildPackageVersion()}Android.apk"); // BuildImp(BuildTargetGroup.Android, BuildTarget.Android, $"{Application.dataPath}/../Build/Android/Android.apk"); } // [MenuItem("AlicizaFramework/Quick Build/一键打包IOS", false, 90)] public static void AutomationBuildIOS() { BuildTarget target = EditorUserBuildSettings.activeBuildTarget; BuildDLLCommand.BuildAndCopyDlls(target); AssetDatabase.Refresh(); BuildInternal(target, outputRoot: Application.dataPath + "/../Bundles", packageVersion: GetBuildPackageVersion()); AssetDatabase.Refresh(); BuildImp(BuildTargetGroup.iOS, BuildTarget.iOS, $"{Application.dataPath}/../Build/IOS/XCode_Project"); } public static void BuildImp(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, string locationPathName) { EditorUserBuildSettings.SwitchActiveBuildTarget(buildTargetGroup, BuildTarget.StandaloneWindows64); AssetDatabase.Refresh(); BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions { scenes = new[] { "Assets/Scenes/main.unity" }, locationPathName = locationPathName, targetGroup = buildTargetGroup, target = buildTarget, options = BuildOptions.None }; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); BuildSummary summary = report.summary; if (summary.result == BuildResult.Succeeded) { Debug.Log($"Build success: {summary.totalSize / 1024 / 1024} MB"); } else { Debug.Log($"Build Failed" + summary.result); } } } }