Created
August 30, 2021 09:42
-
-
Save githappens/eff54ba63c749fef73d2559947effe72 to your computer and use it in GitHub Desktop.
Build method that also triggers an Addressables content build, based on the original build method presented here: https://game.ci/docs/github/builder#buildmethod
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEditor; | |
using UnityEditor.AddressableAssets; | |
using UnityEditor.AddressableAssets.Settings; | |
using UnityEditor.Build.Reporting; | |
using UnityEngine; | |
namespace Ampersand.Editor | |
{ | |
/// <summary> | |
/// This class provides a build method that creates a content build of Addressables before the player is built. | |
/// More info: | |
/// https://game.ci/docs/github/builder#buildmethod | |
/// https://forum.unity.com/threads/how-to-trigger-build-player-content-when-build-unity-project.689602/#post-6798410 | |
/// </summary> | |
internal static class BuildGoAndDesign | |
{ | |
private static readonly string Eol = Environment.NewLine; | |
private static readonly string[] Secrets = | |
{"androidKeystorePass", "androidKeyaliasName", "androidKeyaliasPass"}; | |
public static void Build() | |
{ | |
// Gather values from args | |
Dictionary<string, string> options = GetValidatedOptions(); | |
// Set version for this build | |
PlayerSettings.bundleVersion = options["buildVersion"]; | |
PlayerSettings.macOS.buildNumber = options["buildVersion"]; | |
PlayerSettings.Android.bundleVersionCode = int.Parse(options["androidVersionCode"]); | |
// Enable development build | |
if (bool.TryParse(options["devBuild"], out var isDevBuild)) | |
{ | |
EditorUserBuildSettings.development = isDevBuild; | |
EditorUserBuildSettings.allowDebugging = isDevBuild; | |
EditorUserBuildSettings.waitForManagedDebugger = isDevBuild; | |
} | |
// Apply build target | |
var buildTarget = (BuildTarget) Enum.Parse(typeof(BuildTarget), options["buildTarget"]); | |
switch (buildTarget) | |
{ | |
case BuildTarget.Android: | |
{ | |
EditorUserBuildSettings.buildAppBundle = options["customBuildPath"].EndsWith(".aab"); | |
if (options.TryGetValue("androidKeystoreName", out string keystoreName) && | |
!string.IsNullOrEmpty(keystoreName)) | |
PlayerSettings.Android.keystoreName = keystoreName; | |
if (options.TryGetValue("androidKeystorePass", out string keystorePass) && | |
!string.IsNullOrEmpty(keystorePass)) | |
PlayerSettings.Android.keystorePass = keystorePass; | |
if (options.TryGetValue("androidKeyaliasName", out string keyaliasName) && | |
!string.IsNullOrEmpty(keyaliasName)) | |
PlayerSettings.Android.keyaliasName = keyaliasName; | |
if (options.TryGetValue("androidKeyaliasPass", out string keyaliasPass) && | |
!string.IsNullOrEmpty(keyaliasPass)) | |
PlayerSettings.Android.keyaliasPass = keyaliasPass; | |
break; | |
} | |
case BuildTarget.StandaloneOSX: | |
PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, ScriptingImplementation.Mono2x); | |
break; | |
} | |
// Build addressables content | |
BuildAddressables($"{options["buildTarget"]}-{options["branch"]}"); | |
// Custom build | |
Build(buildTarget, options["customBuildPath"]); | |
} | |
private static void BuildAddressables(string addressablesProfileName) | |
{ | |
Console.WriteLine("Cleaning player content."); | |
AddressableAssetSettings.CleanPlayerContent(); | |
AddressableAssetProfileSettings profileSettings = | |
AddressableAssetSettingsDefaultObject.Settings.profileSettings; | |
Console.WriteLine("Using active databuilder: " + | |
AddressableAssetSettingsDefaultObject.Settings.ActivePlayerDataBuilder.Name); | |
Console.WriteLine("Setting profile to: " + addressablesProfileName); | |
string profileId = profileSettings.GetProfileId(addressablesProfileName); | |
AddressableAssetSettingsDefaultObject.Settings.activeProfileId = profileId; | |
Console.WriteLine("Starting addressables content build."); | |
// Build addressable content | |
AddressableAssetSettings.BuildPlayerContent(); | |
Console.WriteLine("Building player content finished."); | |
} | |
private static Dictionary<string, string> GetValidatedOptions() | |
{ | |
ParseCommandLineArguments(out Dictionary<string, string> validatedOptions); | |
if (!validatedOptions.TryGetValue("projectPath", out string _)) | |
{ | |
Console.WriteLine("Missing argument -projectPath"); | |
EditorApplication.Exit(110); | |
} | |
if (!validatedOptions.TryGetValue("buildTarget", out string buildTarget)) | |
{ | |
Console.WriteLine("Missing argument -buildTarget"); | |
EditorApplication.Exit(120); | |
} | |
if (!Enum.IsDefined(typeof(BuildTarget), buildTarget ?? string.Empty)) | |
{ | |
EditorApplication.Exit(121); | |
} | |
if (!validatedOptions.TryGetValue("customBuildPath", out string _)) | |
{ | |
Console.WriteLine("Missing argument -customBuildPath"); | |
EditorApplication.Exit(130); | |
} | |
const string defaultEnableDevBuildValue = "false"; | |
if (!validatedOptions.TryGetValue("devBuild", out var isDevBuild)) | |
{ | |
Console.WriteLine($"Missing argument -devBuild, defaulting to {defaultEnableDevBuildValue}."); | |
validatedOptions.Add("devBuild", defaultEnableDevBuildValue); | |
} | |
const string defaultCustomBuildName = "TestBuild"; | |
if (!validatedOptions.TryGetValue("customBuildName", out string customBuildName)) | |
{ | |
Console.WriteLine($"Missing argument -customBuildName, defaulting to {defaultCustomBuildName}."); | |
validatedOptions.Add("customBuildName", defaultCustomBuildName); | |
} | |
else if (customBuildName == "") | |
{ | |
Console.WriteLine($"Invalid argument -customBuildName, defaulting to {defaultCustomBuildName}."); | |
validatedOptions.Add("customBuildName", defaultCustomBuildName); | |
} | |
return validatedOptions; | |
} | |
private static void ParseCommandLineArguments(out Dictionary<string, string> providedArguments) | |
{ | |
providedArguments = new Dictionary<string, string>(); | |
string[] args = Environment.GetCommandLineArgs(); | |
Console.WriteLine( | |
$"{Eol}" + | |
$"###########################{Eol}" + | |
$"# Parsing settings #{Eol}" + | |
$"###########################{Eol}" + | |
$"{Eol}" | |
); | |
// Extract flags with optional values | |
for (int current = 0, next = 1; current < args.Length; current++, next++) | |
{ | |
// Parse flag | |
bool isFlag = args[current].StartsWith("-"); | |
if (!isFlag) continue; | |
string flag = args[current].TrimStart('-'); | |
// Parse optional value | |
bool flagHasValue = next < args.Length && !args[next].StartsWith("-"); | |
string value = flagHasValue ? args[next].TrimStart('-') : ""; | |
bool secret = Secrets.Contains(flag); | |
string displayValue = secret ? "*HIDDEN*" : "\"" + value + "\""; | |
// Assign | |
Console.WriteLine($"Found flag \"{flag}\" with value {displayValue}."); | |
providedArguments.Add(flag, value); | |
} | |
} | |
private static void Build(BuildTarget buildTarget, string filePath) | |
{ | |
string[] scenes = EditorBuildSettings.scenes.Where(scene => scene.enabled).Select(s => s.path).ToArray(); | |
var buildPlayerOptions = new BuildPlayerOptions | |
{ | |
scenes = scenes, | |
target = buildTarget, | |
// targetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget), | |
locationPathName = filePath, | |
// options = UnityEditor.BuildOptions.Development | |
}; | |
BuildSummary buildSummary = BuildPipeline.BuildPlayer(buildPlayerOptions).summary; | |
ReportSummary(buildSummary); | |
ExitWithResult(buildSummary.result); | |
} | |
private static void ReportSummary(BuildSummary summary) | |
{ | |
Console.WriteLine( | |
$"{Eol}" + | |
$"###########################{Eol}" + | |
$"# Build results #{Eol}" + | |
$"###########################{Eol}" + | |
$"{Eol}" + | |
$"Duration: {summary.totalTime.ToString()}{Eol}" + | |
$"Warnings: {summary.totalWarnings.ToString()}{Eol}" + | |
$"Errors: {summary.totalErrors.ToString()}{Eol}" + | |
$"Size: {summary.totalSize.ToString()} bytes{Eol}" + | |
$"{Eol}" | |
); | |
} | |
private static void ExitWithResult(BuildResult result) | |
{ | |
switch (result) | |
{ | |
case BuildResult.Succeeded: | |
Console.WriteLine("Build succeeded!"); | |
EditorApplication.Exit(0); | |
break; | |
case BuildResult.Failed: | |
Console.WriteLine("Build failed!"); | |
EditorApplication.Exit(101); | |
break; | |
case BuildResult.Cancelled: | |
Console.WriteLine("Build cancelled!"); | |
EditorApplication.Exit(102); | |
break; | |
case BuildResult.Unknown: | |
default: | |
Console.WriteLine("Build result is unknown!"); | |
EditorApplication.Exit(103); | |
break; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment