How to automate mobile builds in Unity 3D?

tudip-logo

Tudip

05 May 2020

How to launch Unity from the command line?

We can run Unity on both macOS and Windows from the command line.

On macOS, type the following command into the Terminal to launch Unity:

“/Applications/Unity/Unity.app/Contents/MacOS/Unity”

On Windows, type the following command into the Command Prompt to launch Unity:

“C:\Program Files\Unity\Editor\Unity.exe”

Add the following arguments to launch the Unity in silent mode:

-quit: It is used to quit Unity once all the commands are completed.

-batchmode: It is used to run Unity in “headless” mode without GUI.

How to create a Build Pipeline?

Build Pipeline lets us programmatically build players. We can create a custom wrapper for Build Pipelines using Unity’s default BuildPipeline.

Consider the following example of Build Pipeline for both Android and iOS.

public static class Builder
{
    private const char CommandStartCharacter = '-';
    private const string BuildPathCommand = "-buildPath";
    private const string KeystorePasswordCommand = "-keystorePass";
    private const string KeyAliasPasswordCommand = "-keyaliasPass";
    private const string ProvisionProfileId = "-provisionUUID";

    public static void BuildAndroid()
    {
        string buildPath, keystorePassword, keyAliasPassword, androidType;
 //Parse custom command line arguments
        Dictionary<string, string> commandToValueDictionary = GetCommandLineArguments();
        commandToValueDictionary.TryGetValue(BuildPathCommand, out buildPath);
        commandToValueDictionary.TryGetValue(KeystorePasswordCommand, out keystorePassword);
        commandToValueDictionary.TryGetValue(KeyAliasPasswordCommand, out keyAliasPassword);
        //Update Key Store and Alias password
        PlayerSettings.keyaliasPass = keyAliasPassword;
        PlayerSettings.keystorePass = keystorePassword;
        BuildPipeline.BuildPlayer(GetEnabledScenePaths(), buildPath, BuildTarget.Android, BuildOptions.None);
    }

    public static void BuildiOS()
    {
        string buildPath, provisionUUID;
 //Parse command line arguments
        Dictionary<string, string> commandToValueDictionary = GetCommandLineArguments();
        commandToValueDictionary.TryGetValue(BuildPathCommand, out buildPath);
        commandToValueDictionary.TryGetValue(ProvisionProfileId, out provisionUUID);
        //Update iOS Manual provisioning profile to Developer or App Store
        PlayerSettings.iOS.iOSManualProvisioningProfileID = provisionUUID;
        BuildPipeline.BuildPlayer(GetEnabledScenePaths(), buildPath, BuildTarget.iOS, BuildOptions.None);
    }

    private static string[] GetEnabledScenePaths()
    {
        return EditorBuildSettings.scenes.Select(e => e.path).ToArray();
    }

    private static Dictionary<string, string> GetCommandLineArguments()
    {
        Dictionary<string, string> commandToValueDictionary = new Dictionary<string, string>();
        string[] args = Environment.GetCommandLineArgs();
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i].StartsWith(CommandStartCharacter.ToString(), StringComparison.Ordinal))
            {
                string command = args[i];
                string value = string.Empty;
                if (i < args.Length - 1 && !args[i + 1].StartsWith(CommandStartCharacter.ToString(), StringComparison.Ordinal))
                {
                    value = args[i + 1];
                    i++;
                }
                if (!commandToValueDictionary.ContainsKey(command))
                    commandToValueDictionary.Add(command, value);
            }
        }
        return commandToValueDictionary;
    }
}

Build pipeline methods always need to be static methods of a static class. Above build pipeline script have following functionalities:

BuildAndroid / BuildiOS:

Builder class have two public methods, BuildAndroid and BuildiOS, methods to execute build pipeline for Android and iOS platform respectively.

GetCommandLineArguments:

It provides all the custom command line arguments which we could use to update the player settings before building the project.

GetEnabledScenePaths:

It provides an array of all the enabled scenes that are available in the project.

Finally, how to execute the Build Pipeline?

We would need to use -executeMethod command line argument with appropriate method name to execute.

For example

  1. Execute Android Pipeline on MacOS:
    “/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -projectPath "${WORKSPACE}" -executeMethod Builder.BuildAndroid”
  2. Execute iOS Pipeline on MacOS:
    “/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -projectPath "${WORKSPACE}" -executeMethod Builder.BuildiOS”

Please refer Unity manual for the complete list of supported command line arguments:

https://docs.unity3d.com/Manual/CommandLineArguments.html

Please refer Unity manual for the complete reference of PlayerSettings class:

https://docs.unity3d.com/ScriptReference/PlayerSettings.html

Request a quote