Command-line Unity builds
↑How it works and why
Section titled “How it works and why”Unity can build without its graphical interface. -batchmode runs unattended, -quit exits after the synchronous method completes, -projectPath selects the project, and -executeMethod calls a static Editor method. -buildTarget selects the platform before the project is loaded. -nographics avoids initializing a graphics device; omit it if your build includes a step that requires graphics.
The host runs the Editor; the target runs the player. These examples build a native desktop player:
| Host | Shell | Target | Method | Output |
|---|---|---|---|---|
| Windows 10 | Windows PowerShell 5.1 or PowerShell 7 | StandaloneWindows64 |
BuildTools.BuildWindows |
Builds/Windows/Game.exe |
| Windows 11 | Windows PowerShell 5.1 or PowerShell 7 | StandaloneWindows64 |
BuildTools.BuildWindows |
Builds/Windows/Game.exe |
| Linux | Bash | StandaloneLinux64 |
BuildTools.BuildLinux |
Builds/Linux/Game.x86_64 |
Windows 10 and 11 share the Windows x64 build target; test on both if you support both. Use a Unity release that supports your host OS and a supported Linux distribution. Install the matching platform module through Unity Hub and configure valid licensing. IL2CPP also requires the target’s supported compiler/toolchain. Cross-compilation support depends on the host, backend and modules; changing the target argument alone does not install them.
Shared Editor build script
Section titled “Shared Editor build script”Save this in Assets/Editor/BuildTools.cs or an Editor-only assembly. Both entry points use enabled EditorBuildSettings.scenes and release build options. This script does not select a custom Build Profile asset or apply its overrides: use an explicit profile-aware workflow if your project needs those settings. Do not assume the last profile selected in the GUI is active in automation.
#if UNITY_EDITORusing System;using System.IO;using System.Linq;using UnityEditor;using UnityEditor.Build.Reporting;
public static class BuildTools{ public static void BuildWindows() => Build(BuildTarget.StandaloneWindows64, "Builds/Windows/Game.exe");
public static void BuildLinux() => Build(BuildTarget.StandaloneLinux64, "Builds/Linux/Game.x86_64");
private static void Build(BuildTarget target, string output) { if (EditorUserBuildSettings.activeBuildTarget != target) throw new InvalidOperationException("Pass the matching -buildTarget argument");
string[] scenes = EditorBuildSettings.scenes .Where(scene => scene.enabled) .Select(scene => scene.path) .ToArray(); if (scenes.Length == 0) throw new InvalidOperationException("No enabled build scenes");
Directory.CreateDirectory(Path.GetDirectoryName(output)); var options = new BuildPlayerOptions { scenes = scenes, locationPathName = output, target = target, options = BuildOptions.None }; BuildReport report = BuildPipeline.BuildPlayer(options); if (report.summary.result != BuildResult.Succeeded) throw new InvalidOperationException("Player build failed: " + report.summary.result); }}#endifWindows 10 and Windows 11: PowerShell
Section titled “Windows 10 and Windows 11: PowerShell”Run from the project root containing Assets/ and ProjectSettings/. Replace YOUR_VERSION with the installed Editor version or copy its actual executable path. Close any Editor instance using the project. Save as build-windows.ps1 and run in PowerShell; Bash or WSL is not required.
$ErrorActionPreference = 'Stop'$UnityEditor = 'C:\Program Files\Unity\Hub\Editor\YOUR_VERSION\Editor\Unity.exe'if (-not (Test-Path -LiteralPath $UnityEditor)) { throw 'Set UnityEditor to your installed Unity.exe path'}$ProjectPath = (Get-Location).Path$LogPath = Join-Path $ProjectPath 'unity-build-windows.log'$UnityArguments = @( '-batchmode', '-nographics', '-quit', '-projectPath', ('"{0}"' -f $ProjectPath), '-buildTarget', 'StandaloneWindows64', '-executeMethod', 'BuildTools.BuildWindows', '-logFile', ('"{0}"' -f $LogPath))$BuildProcess = Start-Process -FilePath $UnityEditor -ArgumentList $UnityArguments -Wait -PassThru -WindowStyle Hiddenif ($BuildProcess.ExitCode -ne 0) { throw "Unity failed with exit code $($BuildProcess.ExitCode). Read $LogPath"}Start-Process -Wait waits for the Windows GUI executable to finish; -PassThru exposes its exit code. Embedded quotes preserve paths containing spaces. If script execution is restricted, follow your machine’s policy or paste the commands into an interactive PowerShell session.
Linux: Bash
Section titled “Linux: Bash”Run from the same project root with the Linux Editor installed. Replace YOUR_VERSION and adjust the path if Unity Hub installed it elsewhere. Close any Editor instance using the project. Run with bash ./build-linux.sh; the script itself does not need an executable bit.
#!/usr/bin/env bashset -euo pipefailexport UNITY_EDITOR="$HOME/Unity/Hub/Editor/YOUR_VERSION/Editor/Unity"test -x "$UNITY_EDITOR" || { echo 'Set UNITY_EDITOR to the installed Unity executable' >&2; exit 1; }"$UNITY_EDITOR" -batchmode -nographics -quit \ -projectPath "$PWD" \ -buildTarget StandaloneLinux64 \ -executeMethod BuildTools.BuildLinux \ -logFile "$PWD/unity-build-linux.log"With set -e, a failed Unity process makes the shell script fail. Keep the log even on failure. A batch build does not test whether the resulting player starts correctly.
When to use it and what can go wrong
Section titled “When to use it and what can go wrong”-executeMethod needs a static Editor method, not a MonoBehaviour instance. Match the target argument and method. Use synchronous build APIs here so -quit cannot close the Editor before work finishes. An exception makes the batch build fail; inspect the exit code and platform-specific log.
Try it: Build and launch a Windows player on Windows 10 and Windows 11, and a Linux player on Linux. Then disable all build scenes and confirm each script reports failure. Package the entire output directory as described in build output.
