Generally speaking, making a build with Unity is as easy as it gets really. Select your target platform – get some settings done depending on what you are making a build for and then press a button – done!

To be completely honest with you – if you are working on a little side-project as a hobby, that’s probably all you are going to need and there is no point in doing anything else – however, it is nice to know that you can customize this process and a lot of people in professional settings do that.

 

I could start this off by telling you that back in the day there was no possibility as to push out an update for something and that games came as they were and there was no chance to update shit later… but that would be fishy, I mean I am 27 and I haven’t been in the industry for that long afterall… these days, at least thats what it is like where I work… we make a bunch of builds all the time to give our team members the possibility to test out pur progress and in an environment like that it is useful to have some customizations to your build process, making things easier is always nice.

Preparations:

First of all, we need a place to put all our beautiful customizations.

So make a folder named BuildManager (or whatever you prefer, you can call it shithole if you prefer that… I am not your boss) and create subfolders named Editor and Scripts.

(You can have them all in a Tools folder if you want to be super fancy, but I didn’t care enough!)

 

Automating the Build Pipeline:

I’ll give you the basics here, meaning we are generating a build using editor scripting which will allow us to create several builds for multiple platforms by just clicking one button. How? It’s simple, trust me!

I mentioned in the beginning how you usually make a few settings for specific platforms, we will skip this step by setting up a script that does it for us.

Since Unity allows you to access all these settings within UnityEditor.PlayerSettings. Create a new script, mine will be called BuildManagement.cs, within the Editor folder we created earlier.

Now don’t forget to put a using statement for UnityEditor, as this is necessary to access the PlayerSettings. Then you can simply hard-code all your settings.

public class BuildManagement {

  public static void UpdateSettings(BuildTarget _target)
    {
        //You could have general settings here
        PlayerSettings.companyName = "PurpleMylk";
        PlayerSettings.productName = "MyExampleApp";
        PlayerSettings.bundleVersion = "1.3.4";

        //...and use a switch statement for anything platform specific
        switch (_target)
        {
            case BuildTarget.Android:
                AndroidSettings();
                break;
            case BuildTarget.iOS:
                IOSSettings();
                break;
            case BuildTarget.XboxOne:
                XBoxSettings();
                break;
            case BuildTarget.PS4:
                PS4Settings();
                break;
        }
        
    }

    static void AndroidSettings()
    {
        PlayerSettings.Android.androidIsGame = true;
        PlayerSettings.Android.androidTVCompatibility = false;
        PlayerSettings.Android.blitType = AndroidBlitType.Auto;
        PlayerSettings.Android.bundleVersionCode = 3;
        PlayerSettings.Android.keyaliasName = "Some Shitty App";
    }

    static void IOSSettings()
    {
        PlayerSettings.iOS.allowHTTPDownload = false;
        PlayerSettings.iOS.appInBackgroundBehavior = iOSAppInBackgroundBehavior.Suspend;
        PlayerSettings.iOS.buildNumber = "1.3.4";
    }

    static void XBoxSettings()
    {
        PlayerSettings.XboxOne.ContentId = "x456-fB56-cb678";
        PlayerSettings.XboxOne.Description = "Some Shitty Description";
        PlayerSettings.XboxOne.EnablePIXSampling = true;
        PlayerSettings.XboxOne.EnableVariableGPU = false;
    }

    static void PS4Settings()
    {
        PlayerSettings.PS4.applicationParameter1 = 1234;
        PlayerSettings.PS4.appType = 123;
        PlayerSettings.PS4.appVersion = "1.3.4";
        PlayerSettings.PS4.attribUserManagement = false;
    }

}

I can already feel people starting to think “but why would you need that…?” Now, if you are only building for one platform, I agree ain’t nobody needs that but if you keep reading on you’ll understand where this bit comes in handy.

Let’s see how we can make a build via code. For this, you’ll need to access UnityEditor.BuildPipeline, especially the function called BuildPlayer() – this is what is being called when you press the build Button in the editor.

Here is some code:

public class Build
{
    //This is the path to the folder that will hold all of our builds.
    private static string builds_path = Application.dataPath + "/../Builds";

    //We are creating a folder for our builds if we dont have one yet.
    public static void CreateBuildsFoler()
    {
        if(!Directory.Exists(builds_path))
        {
            Directory.CreateDirectory(builds_path);
        }
    }

    //We are going to use this method to figure out which scenes are enabled as these
    //are the ones we will want in our new build!
    private static string[] GetScenes()
    {
        List<string> scenes = new List<string>();
        for(int i = 0; i < EditorBuildSettings.scenes.Length - 1; i++)
        {
            EditorBuildSettingsScene current_scene = EditorBuildSettings.scenes[i];
            if(current_scene.enabled)
            {
                scenes.Add(current_scene.path);
            }
        }

        return (scenes.Count > 0) ? scenes.ToArray() : null;
    }

    //We are updating the PlayerSettings depending on the build we are making and then we actually start the build 
    //and safe it to the folder we had set up.
    public static void StartBuild(BuildTarget _buildTarget, string _buildName)
    {
        BuildManagement.UpdateSettings(_buildTarget);
        string[] scenes = GetScenes();
        string buildPath = builds_path + "/" + _buildTarget + "/" + _buildName;
        BuildPipeline.BuildPlayer(scenes, buildPath, _buildTarget, BuildOptions.None);

    }
}

Now, this is all great and makes sense but how do we call that? Now, this is where editor scripting comes in handy!
I know there is not that much documentation for EditorScripting available online – so let me know if you guys are interested in that – I could write up an article or make a video for you guys.

We shall start by making an EditorWindow for that:

public class BuildMakerEditor : EditorWindow
{
    private Dictionary<BuildTarget, string> build_targets = new Dictionary<BuildTarget, string>();
    private const string prefix = "BuildMaker_";

    public static BuildMakerEditor instance;

    //This function will instantiate our custom editor window
    public static void DisplaySettings()
    {
        instance = (BuildMakerEditor)EditorWindow.GetWindow(typeof(BuildMakerEditor));
        instance.titleContent = new GUIContent("BuildMaker");
    }

    void OnGUI()
    {
        DisplayPossibleTargets();
        
    }

    //This gets all the options for BuildTargets we have and turns displays them as toggles in our custom Editor window.
    void DisplayPossibleTargets()
    {
        Array build_target_opts = Enum.GetValues(typeof(BuildTarget));

        for (int i = 0; i < build_target_opts.Length; i++)
        {
            if (!build_targets.ContainsKey((BuildTarget)build_target_opts.GetValue(i)))
            {
                build_targets.Add((BuildTarget)build_target_opts.GetValue(i), build_target_opts.GetValue(i).ToString());
            } 
        }

        if(build_targets.Count != 0)
        {
            foreach(BuildTarget target in build_targets.Keys)
            {
                string key = prefix + target.ToString();
                bool current_value = EditorPrefs.GetBool(key, false);
                string label;
                build_targets.TryGetValue(target, out label);
                EditorPrefs.SetBool(key, GUILayout.Toggle(current_value, label));
            }
        }

        if(GUILayout.Button("Build", GUILayout.Height(45)))
        {
            StartBuildProcess();
        }
    }

    //We need this to get the actual value of the toggle (weather its ticked or not!)
    bool GetBuildTargetToggleValue(BuildTarget _target)
    {
        return EditorPrefs.GetBool((prefix + _target.ToString()), false);
    }

    //This class will be called when we press our own Build button!
    //It iterates through each of our set toggles and checks if they are selected or not!
    void StartBuildProcess()
    {
        Build.CreateBuildsFoler();
        string build_name = "";
        foreach(KeyValuePair<BuildTarget,string> entry in build_targets)
        {
            if (GetBuildTargetToggleValue(entry.Key))
            {
                build_name = entry.Value;
                Build.StartBuild(entry.Key, entry.Value);
            }
        }

        EditorUtility.DisplayDialog("BuildMaker", "Build process for " + build_name + " has finished!", "OK");
    }
}

Now, this is great and all but you still can’t access it anywhere. You need one more tiny class for it:

public class MenuItems
{
    [MenuItem("TOOLS/BuildMaker/Make Builds")]
    private static void MakeBuilds()
    {
        BuildMakerEditor.DisplaySettings();
    }
}

Tadah! So now you will be able to see a tab for Tools which will allow us to open our EditorWindow!

Liked it? Take a second to support Kristin on Patreon!

Leave a Reply

Your email address will not be published. Required fields are marked *