AlicizaX/Client/Assets/Editor/Build/ReleaseTools.cs
2025-01-26 20:55:39 +08:00

375 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// 打包工具类。
/// <remarks>通过CommandLineReader可以不前台开启Unity实现静默打包以及CLI工作流详见CommandLineReader.cs example1</remarks>
/// </summary>
public static class ReleaseTools
{
// public static void BuildDll()
// {
// string platform = CommandLineReader.GetCustomArgument("platform");
// if (string.IsNullOrEmpty(platform))
// {
// Debug.LogError($"Build Asset Bundle Errorplatform 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 ErroroutputRoot is null");
// return;
// }
//
// string packageVersion = CommandLineReader.GetCustomArgument("packageVersion");
// if (string.IsNullOrEmpty(packageVersion))
// {
// Debug.LogError($"Build Asset Bundle ErrorpackageVersion is null");
// return;
// }
//
// string platform = CommandLineReader.GetCustomArgument("platform");
// if (string.IsNullOrEmpty(platform))
// {
// Debug.LogError($"Build Asset Bundle Errorplatform 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.BuiltinBuildPipeline);
// 启用共享资源打包
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);
}
}
/// <summary>
/// 创建加密类实例
/// </summary>
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);
}
}
}
}