Unity Custom Build
I like to have convenience build functions that I can just select from a menu and a build would be generated in a proper location with all the correct settings. Another benefit of having a Builder class is that these build functions can be invoked from command line and can be executed on the CI. This is why I always create my own Unity Builder in the project.
Clean Up
We can start by creating a simple Builder class that will have one helper function, in this case this function deletes the build folder. I find it convenient to have an easy way to delete previous builds and artifacts.
public static class Builder
{
public const string BuildPath = "Build";
[MenuItem("Kon Build/Delete Build Folder")]
public static void DeleteBuildFolder()
{
if (Directory.Exists(BuildPath))
{
Directory.Delete(BuildPath, true);
}
}
}
Build Number
Next let's add a way to update the project version inside the actual Unity project, this is not required, but I like it.
[MenuItem("Kon Build/Increment Build Number")]
public static void IncrementBuildNumber()
{
string settingAssetPath = "./ProjectSettings/ProjectSettings.asset";
// Read in file contents
string fileContents = File.ReadAllText(settingAssetPath);
// Find version string
int startIndex = fileContents.IndexOf("bundleVersion:", StringComparison.Ordinal);
if (startIndex == -1)
{
return;
}
int endIndex = fileContents.IndexOf("\n", startIndex);
string versionString = fileContents.Substring(startIndex, endIndex - startIndex);
// Split this string into an array of 3 numbers
string[] numbers = versionString.Split(".");
// Convert last string to a number, this will be the build number
string buildString = numbers[^1];
int buildNumber = Int32.Parse(buildString);
// Increment the build number
buildNumber++;
// Replace the last string in the array with our new buildNumber
numbers[^1] = $"{buildNumber}";
// Convert array of multiple strings into a single string
string newVersionString = string.Join(".", numbers);
// Replace the version string in the file contents with the new version string and save contents back to disk
fileContents = fileContents.Replace(versionString, newVersionString);
File.WriteAllText(settingAssetPath, fileContents);
}
Scenes
Next we need a way to select all the scenes that we want to be part of the build. In this case I just copy the list from the build settings.
private static string[] GetListOfScenes()
{
int sceneCount = SceneManager.sceneCountInBuildSettings;
string[] scenes = new string[sceneCount];
for (int i = 0; i < sceneCount; i++)
{
scenes[i] = SceneUtility.GetScenePathByBuildIndex(i);
}
return scenes;
}
iOS
[MenuItem("Kon Build/Build iOS")]
public static void BuildIOS()
{
IncrementBuildNumber();
string buildPath = BuildPath + "/iOS_Device";
string buildName = "iOS Build";
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.locationPathName = buildPath;
buildPlayerOptions.scenes = GetListOfScenes();
buildPlayerOptions.target = BuildTarget.iOS;
// Refresh assets
if (Application.isBatchMode)
{
AssetDatabase.Refresh();
}
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
BuildSummary summary = report.summary;
if (summary.result == BuildResult.Succeeded)
{
Debug.Log($"{buildName} succeeded: {summary.totalSize} bytes");
}
if (summary.result == BuildResult.Failed)
{
Debug.LogError($"{buildName} failed");
}
}
Web
[MenuItem("Kon Build/Build Web")]
public static void BuildWeb()
{
IncrementBuildNumber();
string buildPath = BuildPath + "/WebGL/game";
string buildName = "kon";
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.locationPathName = buildPath;
buildPlayerOptions.scenes = GetListOfScenes();
buildPlayerOptions.target = BuildTarget.WebGL;
// Refresh assets
if (Application.isBatchMode)
{
AssetDatabase.Refresh();
}
BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
BuildSummary summary = report.summary;
if (summary.result == BuildResult.Succeeded)
{
Debug.Log($"{buildName} succeeded: {summary.totalSize} bytes");
}
if (summary.result == BuildResult.Failed)
{
Debug.LogError($"{buildName} failed");
}
}