Skip to content

Instantly share code, notes, and snippets.

@IJEMIN
Last active January 2, 2023 21:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save IJEMIN/cb61d6f8ae71c410e705d2e76903ab4c to your computer and use it in GitHub Desktop.
Save IJEMIN/cb61d6f8ae71c410e705d2e76903ab4c to your computer and use it in GitHub Desktop.
Unity auto chain build helper
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
public class BuildHelper : EditorWindow
{
[Serializable]
public class BuildSetting
{
public string version;
public int versionCode;
public string keystoreName;
public string keystorePassword;
public string aliasName;
public string aliasPassword;
private const string DefaultKeystorePath = "keystoreRelativePathHere";
private const string DefaultKeystorePassword = "keystorePasswordHere";
private const string DefaultAliasName = "aliasNameHere";
private const string DefaultAliasPassword = "aliasPasswordHere";
public BuildSetting()
{
version = PlayerSettings.bundleVersion;
versionCode = PlayerSettings.Android.bundleVersionCode;
keystoreName = !string.IsNullOrEmpty(PlayerSettings.Android.keystoreName)
? PlayerSettings.Android.keystoreName
: DefaultKeystorePath;
keystorePassword = !string.IsNullOrEmpty(PlayerSettings.Android.keystorePass)
? PlayerSettings.Android.keystorePass
: DefaultKeystorePassword;
aliasName = !string.IsNullOrEmpty(PlayerSettings.Android.keyaliasName)
? PlayerSettings.Android.keyaliasName
: DefaultAliasName;
aliasPassword = !string.IsNullOrEmpty(PlayerSettings.Android.keyaliasPass)
? PlayerSettings.Android.keyaliasPass
: DefaultAliasPassword;
}
}
private string _buildSettingDefaultPath;
public BuildSetting buildSetting;
private bool enableAutoRun;
[MenuItem("Window/Build Helper")]
private static void Init()
{
GetWindow(typeof(BuildHelper)).Show();
}
private void OnEnable()
{
_buildSettingDefaultPath = Path.Combine(Application.dataPath, "buildData.json");
if (buildSetting == null) buildSetting = new BuildSetting();
}
private void OnGUI()
{
if (File.Exists(_buildSettingDefaultPath))
if (GUILayout.Button("Load Build Setting from JSON"))
{
var dataAsJson = File.ReadAllText(_buildSettingDefaultPath);
buildSetting = JsonUtility.FromJson<BuildSetting>(dataAsJson);
}
GUILayout.Label("Current Target Build Settings");
var serializedObject = new SerializedObject(this);
var serializedProperty = serializedObject.FindProperty("buildSetting");
EditorGUILayout.PropertyField(serializedProperty, true);
serializedObject.ApplyModifiedProperties();
if (GUILayout.Button("Apply and Save Build Settings"))
{
ApplyCustomBuildSettings();
var jsonData = JsonUtility.ToJson(buildSetting, true);
File.WriteAllText(_buildSettingDefaultPath, jsonData);
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Run after build");
enableAutoRun = EditorGUILayout.Toggle(enableAutoRun);
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Build (current platform)"))
{
var path = EditorUtility.SaveFolderPanel("Select Folder to Save Build", string.Empty, string.Empty);
if (string.IsNullOrEmpty(path)) return;
Build(EditorUserBuildSettings.activeBuildTarget, path, enableAutoRun);
}
if (GUILayout.Button("Chain Build(Android + iOS)")) StartChainBuild(enableAutoRun);
}
private void ApplyCustomBuildSettings()
{
PlayerSettings.bundleVersion = buildSetting.version;
PlayerSettings.Android.bundleVersionCode = buildSetting.versionCode;
PlayerSettings.iOS.buildNumber = buildSetting.versionCode.ToString();
PlayerSettings.Android.keystoreName = buildSetting.keystoreName;
PlayerSettings.Android.keystorePass = buildSetting.keystorePassword;
PlayerSettings.Android.keyaliasName = buildSetting.aliasName;
PlayerSettings.Android.keyaliasPass = buildSetting.aliasPassword;
}
public static void StartChainBuild(bool autoRun)
{
var path = EditorUtility.SaveFolderPanel("Select Folder to Save Build", string.Empty, string.Empty);
if (string.IsNullOrEmpty(path)) return;
Build(BuildTarget.Android, path, autoRun);
Build(BuildTarget.iOS, path, autoRun);
}
public static void Build(BuildTarget buildTarget, string directoryPathToSaveBuild, bool autoRun = false)
{
if (buildTarget == BuildTarget.Android)
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, buildTarget);
else if (buildTarget == BuildTarget.iOS)
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, buildTarget);
else
EditorUserBuildSettings.SwitchActiveBuildTarget(buildTarget);
var scenes = EditorBuildSettings.scenes.Where(scene => scene.enabled).Select(scene => scene.path).ToArray();
var buildFileName = "build";
if (buildTarget == BuildTarget.Android)
buildFileName = $"androidBuild_{LocalizationManager.currentLanguage.ToString()}.apk";
else if (buildTarget == BuildTarget.iOS)
buildFileName = $"iOSBuild_{LocalizationManager.currentLanguage.ToString()}";
var outputPath = Path.Combine(directoryPathToSaveBuild, buildFileName);
if (File.Exists(outputPath)) File.Delete(outputPath);
var playerBuildOption = new BuildPlayerOptions
{
target = buildTarget,
options = autoRun ? BuildOptions.AutoRunPlayer : BuildOptions.None,
scenes = scenes,
locationPathName = outputPath
};
var report = BuildPipeline.BuildPlayer(playerBuildOption);
var summary = report.summary;
if (summary.result == BuildResult.Succeeded)
Debug.Log("Build succeeded: " + summary.totalSize + " bytes");
else if (summary.result == BuildResult.Failed) Debug.LogError("Build failed : " + summary.totalErrors);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment