Effective Unity

The secret of getting ahead is getting started. Mark Twain

Getting started with Unity automation

Automating your Unity project is a great way of saving time and producing higher quality results. It’s also an awesome way of bringing the fun back into development because you need to spend less time on the boring repetitive tasks and can focus on the tasks that actually require a human brain.

So how do you do it? Unity comes with a very powerful API built-in that allows you to automate almost everything that the Unity editor can do with editor scripts. You may say now “but Jan, I’m not a coder, I have no idea about scripting”. And that is totally fine, not everyone is a coder and not everyone needs or wants to be one. You can still automate Unity by:

Now that that is out of the way, back to - editor scripts. Editor scripts are pretty much like your normal MonoBehaviour scripts except that they run inside the Unity editor instead of your game. To let Unity know that a script is an editor script you simply need to put it somewhere below a folder named Editor. It doesn’t matter where this Editor folder resides, it’s just important the the script is inside the Editor folder or a subfolder of the Editor folder (now that was a lot of “Editor” and “folder”). So let’s do that right now. Create a folder Editor in your Unity project and create a new C# script inside of it. Name it HelloUnityAutomation. Then double-click it so it opens in MonoDevelop (or Visual Studio). Now delete everything inside it and replace it with this code:

using UnityEngine;
using UnityEditor;

public class HelloUnityAutomation {

  [MenuItem("Automation/Hello")]
  static void SayHello() {
    Debug.Log ("Hello Unity!");
  }
}

That’s actually not very much code. To understand what it does we go through it piece by piece:

using UnityEngine;
using UnityEditor;

This is pulling in some parts of Unity’s API (if you’re a full-time C# programmer and I’m beginning to bore you, just skip ahead a few paragraphs). The UnityEditor part is only available for editor scripts and it contains all the neat functionality that you need for your automation. Next up we have:

public class HelloUnityAutomation {

This defines a class. If you’re a coder you know what I’m talking about. If not, then for starters just think of a class as some container where you put your functions. It’s name should match the name of the file that it’s in. Now for the interesting stuff:

[MenuItem("Automation/Hello")]

This tells Unity that you want a new item in Unity’s main menu. It will create a new entry in the main menu called Automation which has an entry named Hello.

static void SayHello() {
  Debug.Log ("Hello Unity!");
}

This is the actual function that gets executed when you click that new menu item. Right now it doesn’t an awful lot, it just prints “Hello Unity!” into the console of the Unity editor by using the Debug.Log function. But we’ll add some real automation pretty soon so don’t worry. Now save that file in MonoDevelop (or VS) and go back to the Unity editor. Unity will load the changed file and compile it. In the main menu you should see a new entry called Automation (if not, just click some other menu entry and Unity will refresh the menu). Click Automation, then click Hello. This will print “Hello Unity!” into Unity’s console. If you don’t see the console window, open it up using the main menu Window -> Console.

As you can see it’s rather easy to create an automation for Unity, you only need three steps:

Now while printing “Hello Unity” is certainly exciting, it’s not terribly useful. So let’s add a second automation to this class which does something useful, like building a player. Go back to MonoDevelop and add this right below the SayHello function:

[MenuItem("Automation/Build Player")]
static void BuildPlayer() {
  // get the scenes from the settings dialog
  var scenes = EditorBuildSettings.scenes.Select (it => it.path).ToArray ();

  BuildPipeline.BuildPlayer( // this tells Unity to build a player with:
    // the scenes we got from the settings dialog
    scenes,
    // to put it on the desktop and call it “myPlayer.exe”
    Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/myPlayer.exe",
    // to build it for Windows
    BuildTarget.StandaloneWindows,
    // with no special options
    BuildOptions.None
    );
}

Again lets go through this one by one (and again if you’re a C# expert, you may skip the next few paragraphs as there will be nothing new for you here).

var scenes = EditorBuildSettings.scenes.Select (scene => scene.path).ToArray ();

This is a somewhat more complex expression so let’s strip it down again:

EditorBuildSettings.scenes

This part reads the scenes that are currently set in the editor build settings (you can find these settings in File -> Build Settings). We want to use these scenes when building the player. The problem with that expression is, that it returns a list of EditorBuildSettingsScene objects. The function which builds a player however expects a list of paths to the scenes it should include (more correctly it expects an Array of paths). We therefore need to convert what comes back from the EditorBuildSettings.scenes function into an Array of paths. Each EditorBuildSettingsScene object has a property named path which contains the path to the scene. So we now use the Select function to get the paths from the EditorBuildSettingsScene objects:

EditorBuildSettings.scenes.Select (scene => scene.path)

This returns a list of paths. The Select function is part of a special package called System.Linq. So for it to work, you need to add another “using” directive to the top of your file:

using System.Linq;

Now, since the function for building the player requires an Array (and not a List) we need to convert that List we got back from the Select function into an Array. This is done by the ToArray function:

var scenes = EditorBuildSettings.scenes.Select (scene => scene.path).ToArray ();

So now we have an array of paths in our scenes variable which we can then give to the next function:

BuildPipeline.BuildPlayer(scenes,

BuildPipeline.BuildPlayer builds a Unity player. It can build any kind of Unity player that Unity supports, from Windows/Mac standalone builds, over WebPlayer and HTML5 to Xbox players etc. You need to give it some arguments though, so it knows what to build and where to put it. The first argument is the list of scenes that should be in the player. We extracted this from the build settings, so you can conveniently change the scenes list in the build settings and don’t need to modify your scripts all the time. Next argument is the place where the player should be built.

BuildPipeline.BuildPlayer(scenes,
  Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/myPlayer.exe",

If you can, avoid hardcoding any paths in your automation scripts, as this will make your scripts unusable for other team members who may work on different operating systems and paths. Therefore in the example I’m using the Environment.GetFolderPath function to determine the path to the user’s desktop folder. Then I’m appending "/myPlayer.exe" (I’m going to build Windows player here). Again the Environment class and it’s functions are part of a special package, so we need another using directive at the top of our file:

using System;

The next argument tells the function what kind of player it should build:

BuildPipeline.BuildPlayer(scenes,
  Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/myPlayer.exe",
  BuildTarget.StandaloneWindows,

As I already wrote, I’m going to build a Windows player here. You can of course change this to whatever type of player you want to build. You can find a list of supported options in the Unity documentation. Finally, you can give the function any amount of build options. Since build options are a more advanced topic, we’ll leave them out here and just say we don’t want any specific build option:

BuildPipeline.BuildPlayer(scenes,
  Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/myPlayer.exe",
  BuildTarget.StandaloneWindows,
  BuildOptions.None
);

And that’s it. Now save your file, go back to Unity and let it compile the updated file for you. Then you can open the Automation menu and you’ll find a second option named Build Player. Clicking this, will build a player and put it on your desktop. Congratulations, you just finished your first useful automation for Unity.

If you’re having trouble putting the script together, you can download an example from here. With this you can start implementing your own automations. The Unity API is quite big and it’s easy to get lost. Therefore I have put together an Editor automation cheat sheet which contains links to the API functions that you can use to perform the most common types of automation.

Share this article: Twitter Facebook Google+ eMail