Unity Tutorial: How to Run Specific Code Only When Building Out a Project

Andrei Marks · August 16, 2012

(Unity 3.5.5)

Sometimes you want to make your code to make a change to your project when you build it out, without needing any user action.

An Example Problem

At Cipher Prime we use Google Analytics to collect metrics for our games. We’re interested in how many people complete which levels, how often the game is being played, and sometimes, for contests or demo distributions, we want to know whether our game is being played in the first place.

The way we do this is with a tracking tag, just a string identifier that gets reported through Google Analytics. For instance, the tracking tag for a build we submit to a contest would be “contest+date”.

But because we set the tag manually, one (frequently recurring) problem during the development of Splice was that we would often forget to label a build properly. So I set about creating an automated solution that would generate a descriptive tracking tag every time we built out the game.

In our particular case the solution had three parts: 1) an editor script that updates the tracking tag at the beginning of a build, 2) a prefab that would store the updated tracking tag and 3) be referenced by the actual runtime tracking script.

Step 1: Using the InitializeOnLoad Attribute

Unity doesn’t seem to have a silver bullet method for making sure that a script when you’re building. However, there is a next-best way. InitializeOnLoad is a really handy attribute that will run an editor script whenever scripts recompile. So, when the project is loaded, when you make any changes to project scripts, when you press play in the editor, or when you build out the project.

Now, that might be too often if what you want to do is pretty resource intensive, but if it’s something simpler, then it’s perfectly fine.

There are only a couple things the script requires (see example below):

  1. You need the UnityEditor namespace.
  2. You need the [InitializeOnLoad] tag.
  3. The script's class should have a static constructor.
  4. As with any other editor script, it should be put in an editor folder in your Project.

[csharp] using UnityEngine; using UnityEditor; using System;

[InitializeOnLoad] public class UpdateTrackingCode { public static string trackingTag;

static UpdateTrackingCode()
{
	// Code to be executed on load goes here.
            UpdateTrackingTag();
}

static void UpdateTrackingTag()
{
	// Setting the Tracking Tag
	trackingTag = (DateTime.Now.ToString("yyMMdd") + "_" + EditorUserBuildSettings.activeBuildTarget.ToString());

            // Setting the prefab variable so it can be accessed at runtime.
            GameObject trackingPrefab = (GameObject) Resources.Load("Tracking/TrackingInfo");
	trackingPrefab.GetComponent().trackingTagName = trackingTag;
}

} [/csharp]

See the official Unity documentation and Unify Community for some additional applications of InitializeOnLoad.

Step Two: Link the InitializeOnLoad script to a Scene

Because editor scripts can’t be accessed by runtime scripts, you should be prepared with a solution that allows your InitializeOnLoad script to interact with the the scene or the project. This might mean creating or editing an asset, or adding something to the scene.

In my example, I have the script load up a pre-existing prefab and edit a property (trackingTagName) on a script attached to the Game Object.

[csharp] GameObject trackingPrefab = (GameObject) Resources.Load("Tracking/TrackingInfo"); TrackingPrefab.GetComponent().trackingTagName = trackingTag; [/csharp]

Step Three: Referencing the New Information in the Scene

How this happens will depend on exactly how you did step two.

In our case, now that the editor script changed the prefab, I simply add a reference to the prefab in the scene object responsible for sending tracking messages out.

Remember that it’s also possible to reach directly into a scene from an editor script, but in our case scene switches made it more efficient to edit the prefab. One issue with this approach is that the InitializeOnLoad script runs whenever the project is recompiled, meaning you might run into trouble if you have multiple scenes and not all of them have the proper references.

Twitter, Facebook