I want to execute a build for my DOTS project from command line but I’m unsure how to do it correctly.
Anyone know how to invoke a DOTS build from command line?
I don’t want to accidentally invoke the regular build pipeline since it is not supported.
For completeness, here is the build script I stole from that post and tweaked.
There are 2 ways to invoke it,
Through the Editor top level menu that is created via the [MenuItem] attributes below
Through command line, just by invoking the Unity Editor as you normally would from command line and passing a ‘-executeMethod’ argument, e.g. I have a little Python script
import os
cmd = “”"
“C:\Program Files\Unity\Hub\Editor\2020.3.13f1\Editor\Unity.exe”
-batchmode
-quit
-logFile build.log
-projectPath ./
-executeMethod Krooq.Framework.Editor.Builder.Build
-platform Windows
“”"
os.system(cmd)
The important parts are
You need Unity.Build package referenced in your assembly
This is an Editor script, i.e. it wont be included in your build
I’m using Netcode, so it creates 2 instances for me to test client and server, tweak this as you wish in the menu code
I’m using Addressables so the build does that as well, again, tweak as you wish
I also handle window position using a custom command line arg passed to the game as you would for any other program (code for that was ripped from the DOTS Sample)
You will need to replace the constants with things specific to your game e.g. _buildAssetsDirectory is the directory for your “Build Configuration” assets.
Hope this helps someone, it’s always a pain setting up build tooling.
#if UNITY_EDITOR
using System;
using System.Diagnostics;
using System.Linq;
using Unity.Build;
using UnityEditor;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Krooq.Framework.Editor
{
public static class Builder
{
private const string _buildAssetsDirectory = "Assets/Build";
[MenuItem("Build/[Windows] Build ")]
public static void BuildForWindows() => BuildForPlatform(Platform.Windows);
[MenuItem("Build/[Windows] Run")]
public static void Run()
{
// We run 2 instances of the game, one for a host (who is also a "local" client) and one for a "remote" client.
var exe = $"{Environment.CurrentDirectory}/Builds/DOTS Game/DOTS Game.exe";
var hostLog = $"{Application.persistentDataPath}/Host.log";
var clientLog = $"{Application.persistentDataPath}/Client.log";
Process.Start(exe, $"-windowpos 0,0 -logFile \"{hostLog}\"");
Process.Start(exe, $"-windowpos 1920,0 -logFile \"{clientLog}\"");
Process.Start("Code", $"\"{Application.persistentDataPath}/{Application.productName}.code-workspace\"");
}
[MenuItem("Build/[Windows] Build and Run")]
public static void BuildAndRunForWindows()
{
BuildForWindows();
Run();
}
public static void Build()
{
var platformArg = CommandLineUtil.GetArg("-platform");
var platform = Platform.GetPlatformByName(platformArg);
if (platform != null) BuildForPlatform(platform);
}
private static void BuildForPlatform(Platform platform)
{
try
{
var buildConfiguration = GetBuildConfiguration(platform);
BuildAddressableAssets();
BuildPlayer(buildConfiguration);
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
private static void BuildAddressableAssets()
{
AddressableAssetSettings.BuildPlayerContent();
}
private static BuildConfiguration GetBuildConfiguration(Platform platform)
{
// Check whether the target platform can be build on this machine.
var compatible = false;
switch (platform.Name)
{
case KnownPlatforms.Linux.Name:
if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.WindowsEditor)
compatible = true;
break;
case KnownPlatforms.macOS.Name:
if (Application.platform == RuntimePlatform.OSXEditor)
compatible = true;
break;
case KnownPlatforms.Windows.Name:
case KnownPlatforms.Switch.Name:
if (Application.platform == RuntimePlatform.WindowsEditor)
compatible = true;
break;
}
if (!compatible)
throw new Exception($"Cannot build the player for platform {platform} on this machine");
// Find the platform-specific build configuration asset.
var assetGuids = AssetDatabase.FindAssets($"t:BuildConfiguration {platform.DisplayName}" , new [] { _buildAssetsDirectory});
if (assetGuids.Length < 1) throw new Exception($"Platform {platform} BuildConfiguration not found.");
if (assetGuids.Length > 1) throw new Exception($"Multiple BuildConfigurations found for platform {platform} {assetGuids.Select(AssetDatabase.GUIDToAssetPath).ToList().ToString()}");
// Load the build configuration asset.
var assetPath = AssetDatabase.GUIDToAssetPath(assetGuids[0]);
var buildConfiguration = AssetDatabase.LoadAssetAtPath<BuildConfiguration>(assetPath);
if (!buildConfiguration.CanBuild()) throw new Exception($"Cannot build the player for platform {platform} on this machine");
return buildConfiguration;
}
private static void BuildPlayer(BuildConfiguration buildConfiguration)
{
var result = buildConfiguration.Build();
result.LogResult();
}
}
}
#endif