Skip to content

Instantly share code, notes, and snippets.

@PhalanxHead
Last active March 9, 2021 12:04
Show Gist options
  • Select an option

  • Save PhalanxHead/ecb3552ac8babd117a6c9f07dd7e54a1 to your computer and use it in GitHub Desktop.

Select an option

Save PhalanxHead/ecb3552ac8babd117a6c9f07dd7e54a1 to your computer and use it in GitHub Desktop.
A Full Example of a Unity BuildScript offering builds in Windows (x86 and x64) and Linux, and a corresponding FAKE script.
#r "paket:
nuget Fake.DotNet.Cli
nuget Fake.IO.FileSystem
nuget Fake.Core.Target //"
#load ".fake/build.fsx/intellisense.fsx"
(* Project Constants *)
let ProjectName = "Karter"
let UnitySolutionPath = "./Karter"
let OutputBuildDirectory = "./KarterBuilds"
(* End Project Constants *)
open Fake.Core
open System
open System.IO
open System.IO.Compression
open System.Linq
(* Default Environment Variables *)
let DefaultVersionNumber = "1.0.0.0"
(* End Default Environment Variables *)
(* Environment Variable Names *)
let OutputDirectoryEnvVarName =
(sprintf "%s_OUTPUT_DIRECTORY" (ProjectName.ToUpper()))
let VersionNumberEnvVarName =
(sprintf "%s_VERSION_NUMBER" (ProjectName.ToUpper()))
let BuildNumberEnvVarName =
(sprintf "%s_BUILD_NUMBER" (ProjectName.ToUpper()))
let BuildFullNameEnvVarName =
(sprintf "%s_BUILD_FullName" (ProjectName.ToUpper()))
(* End Environment Variable Names *)
type BuildTarget =
| WindowsX86
| WindowsX64
| Linux
// Path to Unity Installation on current system
let UnityPath =
if Environment.isLinux then
@"/home/guest/Unity/Hub/Editor/2019.4.21f1/Editor/Unity"
elif Environment.isMacOS then
@"/Applications/Unity/Unity.app/Contents/MacOS/Unity"
else
@"C:\Program Files\Unity\Hub\Editor\2019.4.21f1\Editor\Unity.exe"
// Run the Unity Commandline
let RunUnity outputDirectory (target: BuildTarget) =
let scriptMethod =
match target with
| WindowsX64 -> "BuildScript.BuildWindows_x64"
| WindowsX86 -> "BuildScript.BuildWindows_x86"
| Linux -> "BuildScript.BuildLinux_x64"
let result =
Shell.Exec(
UnityPath,
(sprintf
"-quit -batchmode -logFile \"%s\" -projectPath \"%s\" -executeMethod %s"
(Path.Combine(outputDirectory, "Build_Winx64.log"))
UnitySolutionPath
scriptMethod)
)
if result <> 0 then
failwithf "Unity exited with error %d. See Build.log for details" result
// Creates an environment variable and logs its new value, then returns that value.
let SetAndLogEnvironmentVariable variableName variableValue =
Environment.setEnvironVar variableName variableValue
Trace.log (sprintf "%s: %s" (variableName) (Environment.environVar variableName))
Environment.environVar variableName
// Gets the Full Build Name from the EnvironmentVariables
let GetBuildFullName versionNum buildNum = (sprintf "%s_%s" versionNum buildNum)
(* *** Define Targets *** *)
Target.create
"Setup"
(fun _ ->
Trace.log (sprintf "--- Build Started at %A ---" DateTime.Now)
Trace.log " --- Setting up environment variables --- "
let versionNumber =
SetAndLogEnvironmentVariable
VersionNumberEnvVarName
(Environment.environVarOrDefault VersionNumberEnvVarName DefaultVersionNumber)
let buildNumber =
SetAndLogEnvironmentVariable
BuildNumberEnvVarName
(Environment.environVarOrDefault
BuildNumberEnvVarName
(new string (Guid.NewGuid().ToString().Take(8).ToArray())))
let buildFullName =
SetAndLogEnvironmentVariable BuildFullNameEnvVarName (GetBuildFullName versionNumber buildNumber)
Trace.log (sprintf "Output Build Directory: %s" OutputBuildDirectory)
let outbuild = Path.GetFullPath(OutputBuildDirectory)
Trace.log (sprintf "OutBuild: %s" outbuild)
let outputDirectory =
SetAndLogEnvironmentVariable OutputDirectoryEnvVarName (Path.Combine(outbuild, buildFullName))
Directory.CreateDirectory(outputDirectory)
|> ignore
Trace.log " --- Finished setting up environment variables --- ")
Target.create
"UnitTest"
(fun _ ->
Trace.log " --- Running Unit Tests --- "
let loggingDirectory =
Environment.environVar OutputDirectoryEnvVarName
let result =
Shell.Exec(
UnityPath,
(sprintf
"Unity -runTests -batchmode -nographics -logFile \"%s\" -projectPath \"%s\" -testResults \"%s\" -testPlatform editmode "
(Path.Combine(loggingDirectory, "UnitTests.log"))
UnitySolutionPath
(Path.Combine(loggingDirectory, "TestResults.xml")))
)
if result <> 0 then
failwithf "Unity exited with error %d. See UnitTests.log for details" result
Trace.log " --- Finished Running Unit Tests --- ")
Target.create
"BuildWin64"
(fun _ ->
Trace.log " --- Building the Win64 app --- "
RunUnity(Environment.environVar OutputDirectoryEnvVarName) WindowsX64
Trace.log " --- Finished Building the Win64 app --- ")
Target.create
"BuildWinx86"
(fun _ ->
Trace.log " --- Building the Win64 app --- "
RunUnity(Environment.environVar OutputDirectoryEnvVarName) WindowsX86
Trace.log " --- Finished Building the Win64 app --- ")
Target.create
"BuildLinux"
(fun _ ->
Trace.log " --- Building the Win64 app --- "
RunUnity(Environment.environVar OutputDirectoryEnvVarName) Linux
Trace.log " --- Finished Building the Win64 app --- ")
Target.create
"Packaging"
(fun _ ->
Trace.log (sprintf "--- Packaging Application ---")
let zippedFilepath =
(sprintf "./%s_%s.zip" ProjectName (Environment.environVar BuildFullNameEnvVarName))
let buildDirectory =
(Environment.environVar OutputDirectoryEnvVarName)
ZipFile.CreateFromDirectory(buildDirectory, zippedFilepath)
Trace.log (sprintf "--- Build Completed at %A ---" DateTime.Now))
(* *** End Define Targets *** *)
open Fake.Core.TargetOperators
(* *** Dependency Trees *** *)
"Setup"
==> "UnitTest"
==> "BuildWin64"
==> "BuildWinx86"
==> "BuildLinux"
==> "Packaging"
(* *** End Dependency Trees *** *)
(* *** Start Build *** *)
Target.runOrDefaultWithArguments "Packaging"
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class BuildScript
{
// Change this variable to match your project name
private const string _projectName = "Karter";
// The following constants indicate the child folder that builds are output to.
private const string LinuxX64Dir = "Linux_x64";
private const string WindowsX64Dir = "Windows_x64";
private const string WindowsX86Dir = "Windows_x86";
// The following variables are set at build-script-run-time. They are set via Environment Variables, or defaulted to a value in the constructor.
private static readonly string _outputDirectory;
private static readonly string _versionNumber;
private static readonly string _buildNumber;
static BuildScript()
{
_outputDirectory = Environment.GetEnvironmentVariable($"{_projectName.ToUpper()}_OUTPUT_DIRECTORY");
if(string.IsNullOrEmpty(_outputDirectory))
{
_outputDirectory = Application.persistentDataPath;
}
_versionNumber = Environment.GetEnvironmentVariable($"{_projectName.ToUpper()}_VERSION_NUMBER");
if(string.IsNullOrEmpty(_versionNumber))
{
_versionNumber = "1.0.0.0";
}
_buildNumber = Environment.GetEnvironmentVariable($"{_projectName.ToUpper()}_BUILD_NUMBER");
if (string.IsNullOrEmpty(_buildNumber))
{
_buildNumber = new string(Guid.NewGuid().ToString().Take(8).ToArray());
}
PlayerSettings.productName = _projectName;
PlayerSettings.bundleVersion = _versionNumber;
}
static void BuildLinux_x64()
{
var linuxDir = Path.Combine(_outputDirectory, LinuxX64Dir, $"{_projectName}.x86_64");
var pipeline = BuildPipeline.BuildPlayer(GetScenes(), linuxDir, BuildTarget.StandaloneLinux64, BuildOptions.None);
if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
Debug.Log($"Build Succeeded at {DateTimeOffset.Now}");
EditorApplication.Exit(0);
}
else if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Failed)
{
Debug.Log($"Build Failed!\nReport:\n{pipeline.summary.totalErrors}");
EditorApplication.Exit(1);
}
}
static void BuildWindows_x64()
{
var windowsDir = Path.Combine(_outputDirectory, WindowsX64Dir, $"{_projectName}.exe");
var pipeline = BuildPipeline.BuildPlayer(GetScenes(), windowsDir, BuildTarget.StandaloneWindows64, BuildOptions.None);
if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
Debug.Log($"Build Succeeded at {DateTimeOffset.Now}");
EditorApplication.Exit(0);
}
else if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Failed)
{
Debug.Log($"Build Failed!\nReport:\n{pipeline.summary.totalErrors}");
EditorApplication.Exit(1);
}
}
static void BuildWindows_x86()
{
var windowsDir = Path.Combine(_outputDirectory, WindowsX86Dir, $"{_projectName}.exe");
var pipeline = BuildPipeline.BuildPlayer(GetScenes(), windowsDir, BuildTarget.StandaloneWindows, BuildOptions.None);
if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
Debug.Log($"Build Succeeded at {DateTimeOffset.Now}");
EditorApplication.Exit(0);
}
else if(pipeline.summary.result == UnityEditor.Build.Reporting.BuildResult.Failed)
{
Debug.Log($"Build Failed!\nReport:\n{pipeline.summary.totalErrors}");
EditorApplication.Exit(1);
}
}
// Gets all enabled scenes to build from. This can be changed to use strings in the form "Assets/<SceneName>.unity" if required.
private static string[] GetScenes()
{
return EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment