If you are deploying your game to multiple distribution platforms (e.g. SynthesisVR, Steam, etc) and you are looking for a way to easily deploy new versions across all stores, the Unity Build Scripts is your solution.
Step 1 – under the Asset folder your Unity project, create a new folder called “Editor”:
Step 2 – Inside the “Editor” folder, create and open a new C# Script (you can put your own name):
Step 3 – Use the following file template:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
class UploadToAllPlatforms
{
static List<string> allGameScenes = new List<string>() {
"Assets/AllScenes/MainScene.unity",
"Assets/AllScenes/Level1.unity",
"Assets/AllScenes/Level2.unity"
};
static string primaryOutputDirectory = @"E:\UnityBUilds\GameName\";
static Dictionary<string, Platform> allPlatforms = new Dictionary<string, Platform>() { };
class Cmd
{
internal string Path = null;
internal string Arguments = null;
}
class Platform
{
internal BuildTarget target = BuildTarget.StandaloneWindows64;
internal BuildOptions options = BuildOptions.CompressWithLz4HC;
internal List<string> scenes = allGameScenes; // Adopt your predefined list of scenes or add/remove scenes if necessary:
internal string output = null;
internal List<Cmd> onSuccessCommandLineActions = new List<Cmd>();
internal List<GameObject> platformSpecificObjects = new List<GameObject>();
}
static Dictionary<string, Platform> allPlatforms = new Dictionary<string, Platform>() { };
static void ProcessAllPlatforms() {
}
}
Step 4 – Start adding per-platform actions to ProcessAllPlatforms(). In the case of SynthesisVR, you would likely have 4 builds – one for PCVR ; one for Quest ; one for Pico and one for HTC Focus 3:
Create a #region that will handle all 4 builds and add some global Synthesis settings to it:
#region SynthesisVR - All Builds
var synthesisVRcmd = @"""D:\Tools\SynthesisProducer\SynthesisVR - Producer Content Manager.exe""";
var synthesisVRlogin = "yourdevaccount";
var synthesisVRpassword = "yourdevaccount_password";
var synthesisVRgameid = "0000";
var synthesisVRgameObjects = new List<GameObject>() { GameObject.Find("SynthesisRootObject") };
#endregion SynthesisVR - All Builds
Step 5.1 – Add the Synthesis PCVR build before the end region:
#region PCVR Build for SynthesisVR
var svr_PCVR = new Platform();
svr_PCVR.platformSpecificObjects = synthesisVRgameObjects;
// Specify the local folder where the final platform build will be stored:
svr_PCVR.output = primaryOutputDirectory + @"SynthesisVR\PCVR\GameName.exe";
// Each platform provides it's own set of upload tools.
svr_PCVR.onSuccessCommandLineActions.Add(new Cmd {
Path = synthesisVRcmd,
Arguments = $"-autologin -autoupload -user={synthesisVRlogin} -pass={synthesisVRpassword} -gameid={synthesisVRgameid} -type=pcvr -basepath=\"" + Path.GetDirectoryName(svr_PCVR.output) + "\" -exe=\"" + Path.GetFileName(svr_PCVR.output) + "\""
});
allPlatforms.Add("SynthesisVR_PCVR", svr_PCVR);
#endregion PCVR Build for SynthesisVR
Step 5.2 – Add the Synthesis Quest standalone build:
#region Quest Standalone Build for SynthesisVR
var svr_Android_Quest = new Platform();
svr_Android_Quest.platformSpecificObjects = synthesisVRgameObjects;
svr_Android_Quest.output = primaryOutputDirectory + @"SynthesisVR\Quest\GameName.apk";
svr_Android_Quest.target = BuildTarget.Android;
svr_Android_Quest.onSuccessCommandLineActions.Add(new Cmd
{
Path = synthesisVRcmd,
Arguments = $"-autologin -autoupload -user={synthesisVRlogin} -pass={synthesisVRpassword} -gameid={synthesisVRgameid} -type=quest -basepath=\"" + svr_Android_Quest.output + "\""
});
allPlatforms.Add("SynthesisVR_Quest", svr_Android_Quest);
#endregion Quest Standalone Build for SynthesisVR
Step 5.3 – Do the same for Pico and Focus 3:
#region Pico Standalone Build for SynthesisVR
var svr_Android_Pico = new Platform();
svr_Android_Pico.platformSpecificObjects = synthesisVRgameObjects;
svr_Android_Pico.output = primaryOutputDirectory + @"SynthesisVR\Pico\GameName.apk";
svr_Android_Pico.target = BuildTarget.Android;
svr_Android_Pico.onSuccessCommandLineActions.Add(new Cmd
{
Path = synthesisVRcmd,
Arguments = $"-autologin -autoupload -user={synthesisVRlogin} -pass={synthesisVRpassword} -gameid={synthesisVRgameid} -type=pico -basepath=\"" + svr_Android_Pico.output + "\""
});
allPlatforms.Add("SynthesisVR_Quest", svr_Android_Pico);
#endregion Pico Standalone Build for SynthesisVR
#region Focus 3 Standalone Build for SynthesisVR
var svr_Android_Focus3 = new Platform();
svr_Android_Focus3.platformSpecificObjects = synthesisVRgameObjects;
svr_Android_Focus3.output = primaryOutputDirectory + @"SynthesisVR\Focus3\GameName.apk";
svr_Android_Focus3.target = BuildTarget.Android;
svr_Android_Focus3.onSuccessCommandLineActions.Add(new Cmd
{
Path = synthesisVRcmd,
Arguments = $"-autologin -autoupload -user={synthesisVRlogin} -pass={synthesisVRpassword} -gameid={synthesisVRgameid} -type=htc -basepath=\"" + svr_Android_Focus3.output + "\""
});
allPlatforms.Add("SynthesisVR_Quest", svr_Android_Focus3);
#endregion Focus 3 Standalone Build for SynthesisVR
This is what your ProcessAllPlatforms() class would look like:
Step 6 – Analogically, create more regions for Steam and other platforms
Step 7 – Create one extra region at the bottom of ProcessAllPlatforms():
#region Process the builds
var allCommandLineArguments = System.Environment.GetCommandLineArgs();
foreach (var platformName in allCommandLineArguments)
{
if (allPlatforms.ContainsKey(platformName))
{
UnityEngine.Debug.Log($"Building Platform: {platformName}");
var platform = allPlatforms[platformName];
if (platform.output != null)
{
if (Directory.Exists(platform.output))
{
DirectoryInfo di = new DirectoryInfo(platform.output);
try
{
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
}
catch (Exception ex)
{
UnityEngine.Debug.Log("ERROR: Cleaning up directory failed: " + ex.Message);
}
try
{
Directory.Delete(platform.output, true);
}
catch (Exception e)
{
UnityEngine.Debug.Log($"Unable to delete directory: {platform.output}");
}
}
// Enable my GameObjects + Disable GameObjects from other platforms
foreach (var subPlatform in allPlatforms)
{
if (subPlatform.Key != platformName)
{
foreach (var obj in subPlatform.Value.platformSpecificObjects)
{
obj.SetActive(false);
}
}
else
{
foreach (var obj in subPlatform.Value.platformSpecificObjects)
{
obj.SetActive(true);
}
}
}
// Perform the actual build:
BuildReport report = BuildPipeline.BuildPlayer(platform.scenes.ToArray(), platform.output, platform.target, platform.options);
BuildSummary summary = report.summary;
if (summary.result == BuildResult.Succeeded)
{
UnityEngine.Debug.Log($"{platformName} Build succeeded: " + summary.totalSize + " bytes");
foreach(var runCmd in platform.onSuccessCommandLineActions)
{
if (File.Exists(runCmd.Path))
{
Process cmd = new Process();
cmd.StartInfo.FileName = runCmd.Path;
cmd.StartInfo.WorkingDirectory = Path.GetDirectoryName(runCmd.Path);
cmd.StartInfo.Arguments = runCmd.Arguments ?? "";
cmd.Start();
cmd.WaitForExit();
}
}
}
else if (summary.result == BuildResult.Failed)
{
UnityEngine.Debug.LogError($"{platformName} Build failed");
}
}
}
}
#endregion Process the builds
Step 7 (FINAL)
Locate the exe of your Unity Editor.
Example: J:\Program Files (x86)\Unity-EditorVR\Editor\Unity.exe
Create a .BAT script somewhere on your PC and put the following line:
"J:\Program Files (x86)\Unity-EditorVR\Editor\Unity.exe" -quit -batchmode -username "UNITY_USER_NAME" -password "UNITY_PASS" -logFile "C:\Unity_Automated_Build.log" -executeMethod UploadToAllPlatforms.ProcessAllPlatforms svr_PCVR svr_Android_Quest svr_Android_Pico svr_Android_Focus3
Note – you can build just specific platforms by controlling the command line arguments (svr_PCVR ; svr_Android_Quest ; etc)
Launch the BAT file and let it prepare and upload the builds.