Unity IPreprocessBuild & IPostprocessBuild

In Unity you will find yourself wanting to do some process before you build a game, whether it be Asset Bundles, moving platform specific assets to Streaming Assets or just ensuring the build version information is up to date.

The generally advised way is to create your own build script and call BuildPipeline.BuildPlayer yourself. This is easy to do, here is a cut down snippet of the default Wwise example script.

public class AkExampleAppBuilderBase : MonoBehaviour {
	[UnityEditor.MenuItem("File/Build Unity-Wwise Project")]
	public static bool Build() {        
		string appPath = EditorUtility.SaveFilePanel( ...//Choose app name and location
		if (appPath == "") ...//check if the build was cancelled
		PopulateSourceAndDestinationFolderPaths();	
		if (!AkUtilities.DirectoryCopy( ...//Copy the soundbank from the Wwise project to the unity project 	
		string[] scenes = new string[EditorBuildSettings.scenes.Length];
		...//Get all the scenes to build as defined in File->Build Settings
		
		BuildPipeline.BuildPlayer(scenes,appPath,EditorUserBuildSettings.activeBuildTarget,BuildOptions.None);	
		Directory.Delete(destinationSoundBankFolder, true);

The script copies the platform specific sound banks to the streaming assets folder then calls BuildPipeline.BuildPlayer. This keeps build sizes down, and ensures the correct sound banks are used for each platform.

It can quickly be extended to use the various other build settings in the Unity build menu, but it gets out of hand if you just want to a build that copies over the sound banks. This also causes a disconnect between the build settings and the build script; either the build script is fully custom and completely ignores the build settings, or it ignores only certain settings requiring anyone building to check the script to see what it is doing.

Of course, this is perfect if you want to restrict the build process to specific settings, but if you just want the build settings to work for everyone through the normal build menu this is overkill and a pain to maintain.

IPreprocessBuild & IPostprocessBuild

Using IPreprocessBuild OnPreprocessBuild & IPostprocessBuild OnPostprocessBuild or using the attribute version allows you to define basic tasks before and after a unity build runs. This example uses the interface but both work basically the same.

using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;

public class WwiseUnityAppBuildCallbacks : IPreprocessBuild, IPostprocessBuild {

	[SerializeField]
	private static string sourceSoundBankFolder = "";

	[SerializeField]
	private static string destinationSoundBankFolder = "";

	public int callbackOrder { get { return 0; } }

	public void OnPreprocessBuild(BuildTarget target, string path) {

		PopulateSourceAndDestinationFolderPaths();
		Debug.Log("Copying " + sourceSoundBankFolder + "\nTo " + destinationSoundBankFolder);

		//Copy the soundbank from the Wwise project to the unity project (Inside the StreamingAssets folder as defined in Window->Wwise Settings)
		if (!AkUtilities.DirectoryCopy(sourceSoundBankFolder,   //source folder
			destinationSoundBankFolder,                         //destination
			true                                                //copy subfolders
		)) {
			Debug.LogError("WwiseUnity: The soundbank folder for the " + target + " platform doesn't exist. Make sure it was generated in your Wwise project");
		}

		LittleLot.CommonGitCommands.UpdateBundleVersion();
	}

	public void OnPostprocessBuild(BuildTarget target, string path) {

		PopulateSourceAndDestinationFolderPaths();

		Debug.Log("Deleting " + destinationSoundBankFolder);
		//Delete the soundbank from the unity project so they don't get copied in the game folder of future builds
		Directory.Delete(destinationSoundBankFolder, true);
		// Delete meta file, stops error in unity.
		File.Delete(destinationSoundBankFolder + ".meta");
	}
}

Unity 2018.1

IPreprocessBuild changes to IPreprocessBuildWithReport

(BuildTarget target, string path) changes to (BuildReport report)

This class will have its respective functions called before and after building, this means it will add the platform specific sound banks to streaming assets, and after the build completes it will delete them from streaming assets. All Unity build settings will be honoured no need for extra options. It also runs from the standard Build Settings menu; Build and Build & Run will work like normal but have the correct assets in the streaming assets folder. This has the added benefit that anyone on your project can just hit Build & Run and it will work, no hidden menu, no constantly updating and modifying the build script for different settings.

Sadly, this is not perfect for every project but for some things it is preferable to writing an entire custom build script.

Interestingly LittleLot.CommonGitCommands.UpdateBundleVersion(); is one of my utility functions that ensures that the bundle version Unity uses is matched to a specific commit, this is useful for knowing exactly when an issue started to appear, but this would be useless if our builds didn’t automatically update it.

Related

comments powered by Disqus