Unity Build Automation
Automatically create and deploy new Unity builds using a command line script
All of the different builds needed for Dr. Spacezoo are compiled, packaged, and uploaded via a single monolithic build script. This article will detail the scripting defines, target platform configurations, and other parameters used to automatically build and package for multiple OS platforms.
This build script utilizes Unity’s Command line compiling to set Scripting Define Symbols and Target Platform. These Scripting Define Symbols allow Unity to include/exclude, configure, etc. code and variables based on the build target and other parameters (demo vs full version etc).
Here’s an example of the command line build script compiling, packaging, and uploading the full Win/Mac/Linux version of Dr. Spacezoo:
Additionally, be sure to read Unity Build Automation with Jenkins as another option for automating builds.
Player settings
Code is excluded or included, and variables are configured based on the Scripting Define Symbols in the Player Settings. The Scripting Define Symbols are set at:
Build Settings -> Player Settings -> Other Settings -> Scripting Define Symbols
Here’s an example of setting the APP_NAME string based on the version define in player settings:
#if DRSPACEZOO_VER_DEVELOPMENT
public const string APP_NAME = "Dev (Alpha)";
#elif DRSPACEZOO_VER_ITCH_FULL
public const string APP_NAME = "Itch.io (Alpha)";
#elif DRSPACEZOO_VER_ITCH_DEMO
public const string APP_NAME = "Itch.io (Demo)";
#else
public const string APP_NAME = "Dev (Alpha)";
#endif
Editor Script
This is how the Scripting Define Symbols and Build Target are set via the build script. Note, to use -executeMethod in the build script, this editor script needs to reside in ProjectName/Assets/Editor/ and the methods to be executed must be defined as static.
using UnityEditor;
// this will set player defines when building from command line
public static class SRSpaceZooBuild {
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
public static void buildVersion_DevelopmentWeb(){
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.WebPlayer, "DRSPACEZOO_DEMO,DRSPACEZOO_VER_DEVELOPMENT,DRSPACEZOO_WEBBUILD");
}
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
public static void buildVersion_Development(){
// set before build phase
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, "DRSPACEZOO_FULL,DRSPACEZOO_VER_DEVELOPMENT");
}
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
public static void buildVersion_ItchFull(){
// set before build phase
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, "DRSPACEZOO_FULL,DRSPACEZOO_VER_ITCH_FULL");
}
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
public static void buildVersion_ItchDemo(){
// set before build phase
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, "DRSPACEZOO_DEMO,DRSPACEZOO_VER_ITCH_DEMO");
}
}
Bash Build Script
The bash build script sets the build target, compiles, compresses, uploads, etc. I fire the build script off and come back 15 minutes later to hot and ready builds. Note, Unity needs to be fully closed for this script to work.
Here’s an example build command to build the full Win/Mac/Linux version of Dr. Spacezoo and upload to itch.io: ./buildAll.sh v0.6.3 itch yes
The “-executeMethod SRSpaceZooBuild.buildVersion_x” methods used in the script below are the static methods defined in the Editor script above that set the Scripting Define Symbols for the indicated build target (e.g. Standalone).
#!/bin/bash
clear
# command line parms
APP_VERSION=$1
APP_BUILD=$2
APP_UPDATE_PUSH=$3
# help?
if [ $# -ne 3 ] || [ $APP_VERSION == "help" ] || [ $APP_VERSION == "-?" ] || [ $APP_VERSION == "-h" ]; then
echo "usage: ./buildAll.sh v0.x.y type push"
echo " type: all, web, webgl, itch, itchdemo, steam, magfest, indiedb"
echo " push: yes, no"
echo " ./buildAll.sh v0.6.0 itch no"
echo " ./buildAll.sh v0.6.0 steam yes"
echo " ./buildAll.sh v0.6.0 all no"
exit;
fi
# vars
APP_NAME="DrSpacezoo"
APP_NAME_WIN_EXT=".exe"
# set these to your locations
PATH_PROJECT="/Users/user/DrSpacezoo/DrSpacezoo/"
PATH_FINAL_ZIPS="/Users/user/Desktop/builds/final/"
PATH_BUILD="/Users/user/Desktop/builds/auto/"
# I put a symlink from /Users/user/Library/Application Support/itch/bin/butler to this folder.
ITCH_BUTLER_PATH=/Users/user/projectpath/builds/butler # symlink to /Users/user/Library/Application Support/itch/bin/butler
ITCH_BUTLER_CHANNEL_WIN="smashriot/dr-spacezoo:win-release";
ITCH_BUTLER_CHANNEL_OSX="smashriot/dr-spacezoo:osx-release";
ITCH_BUTLER_CHANNEL_LINUX="smashriot/dr-spacezoo:linux-release";
ITCH_BUTLER_VERSION="--userversion";
# build names
PATH_DEV_WEB="DrSpacezoo-Dev-Web"
# itch
PATH_ITCH_WIN_FULL="DrSpacezoo-Itch-Win-Full"
PATH_ITCH_MAC_FULL="DrSpacezoo-Itch-Mac-Full"
PATH_ITCH_LINUX_FULL="DrSpacezoo-Itch-Linux-Full"
# itch demo
PATH_ITCH_WIN_DEMO="DrSpacezoo-Itch-Win-Demo"
PATH_ITCH_MAC_DEMO="DrSpacezoo-Itch-Mac-Demo"
PATH_ITCH_LINUX_DEMO="DrSpacezoo-Itch-Linux-Demo"
# ==========================================
# this moves old build directory and creates a new build directory
# ==========================================
echo "Starting $APP_BUILD builds for $APP_NAME $APP_VERSION."
/bin/mv "/Users/user/Desktop/builds/" "/Users/user/Desktop/builds_old/"
/bin/mkdir "/Users/user/Desktop/builds/"
/bin/mkdir $PATH_BUILD
/bin/mkdir $PATH_FINAL_ZIPS
# ==========================================
# should try to quit unity if it is running or this won't work
# ==========================================
# this doesnt work
#/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit
# ==========================================
# Unity WebPlayer
# ==========================================
if [ $APP_BUILD == "all" ] || [ $APP_BUILD == "web" ]; then
echo "Building Web:Dev to: $PATH_FINAL_ZIPS$PATH_DEV_WEB"
/bin/mkdir $PATH_FINAL_ZIPS$PATH_DEV_WEB
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_DevelopmentWeb -projectPath $PATH_PROJECT -buildWebPlayer $PATH_FINAL_ZIPS$PATH_DEV_WEB"/"$APP_NAME -quit
fi
# ==========================================
# ITCH FULL - These now push the app to itch.io via butler
# ==========================================
if [ $APP_BUILD == "all" ] || [ $APP_BUILD == "itch" ]; then
echo "Building Itch:Win:Full"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_WIN_FULL
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchFull -projectPath $PATH_PROJECT -buildWindowsPlayer $PATH_BUILD$PATH_ITCH_WIN_FULL"/"$APP_NAME$APP_NAME_WIN_EXT -quit
echo "Removing PDB files.."
rm -f $PATH_ITCH_WIN_FULL"/"player_win_x86_s.pdb
rm -f $PATH_ITCH_WIN_FULL"/"player_win_x86.pdb
echo "Compressing Itch:Win:Full"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_WIN_FULL"-"$APP_VERSION".zip" $PATH_ITCH_WIN_FULL
# example: /Users/user/Library/Application\ Support/itch/bin/butler push DrSpacezoo-Itch-Mac-Full-0.6.3.zip smashriot/dr-spacezoo:osx-release --userversion 0.6.3
if [ $APP_UPDATE_PUSH == "yes" ]; then
echo "Pushing to Itch:Win:Full via Butler" #: $ITCH_BUTLER_PATH push $PATH_BUILD$PATH_ITCH_WIN_FULL $ITCH_BUTLER_CHANNEL_WIN $ITCH_BUTLER_VERSION $APP_VERSION"
$ITCH_BUTLER_PATH "push" "$PATH_BUILD$PATH_ITCH_WIN_FULL" "$ITCH_BUTLER_CHANNEL_WIN" "$ITCH_BUTLER_VERSION" "$APP_VERSION"
fi
# --------------
echo "Building Itch:Mac:Full"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_MAC_FULL
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchFull -projectPath $PATH_PROJECT -buildOSXPlayer $PATH_BUILD$PATH_ITCH_MAC_FULL"/"$APP_NAME -quit
# an older version of unity wasn't copying in the icon for Mac, so these two lines fix that issue.
cp "/Users/user/projectpath/builds/ScreenSelector.tif" $PATH_BUILD$PATH_ITCH_MAC_FULL"/"$APP_NAME".app/Contents/Resources/ScreenSelector.tif"
cp "/Users/user/projectpath/builds/PlayerIcon.icns" $PATH_BUILD$PATH_ITCH_MAC_FULL"/"$APP_NAME".app/Contents/Resources/PlayerIcon.icns"
echo "Compressing Itch:Mac:Full"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_MAC_FULL"-"$APP_VERSION".zip" $PATH_ITCH_MAC_FULL
if [ $APP_UPDATE_PUSH == "yes" ]; then
echo "Pushing to Itch:Mac:Full via Butler" #: $ITCH_BUTLER_PATH push $PATH_BUILD$PATH_ITCH_MAC_FULL $ITCH_BUTLER_CHANNEL_OSX $ITCH_BUTLER_VERSION $APP_VERSION"
$ITCH_BUTLER_PATH "push" "$PATH_BUILD$PATH_ITCH_MAC_FULL" "$ITCH_BUTLER_CHANNEL_OSX" "$ITCH_BUTLER_VERSION" "$APP_VERSION"
fi
# --------------
echo "Building Itch:Linux:Full"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_LINUX_FULL
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchFull -projectPath $PATH_PROJECT -buildLinuxUniversalPlayer $PATH_BUILD$PATH_ITCH_LINUX_FULL"/"$APP_NAME -quit
echo "Compressing Itch:Linux:Full"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_LINUX_FULL"-"$APP_VERSION".zip" $PATH_ITCH_LINUX_FULL
if [ $APP_UPDATE_PUSH == "yes" ]; then
echo "Pushing to Itch:Linux:Full via Butler" #: $ITCH_BUTLER_PATH push $PATH_BUILD$PATH_ITCH_LINUX_FULL $ITCH_BUTLER_CHANNEL_LINUX $ITCH_BUTLER_VERSION $APP_VERSION"
$ITCH_BUTLER_PATH "push" "$PATH_BUILD$PATH_ITCH_LINUX_FULL" "$ITCH_BUTLER_CHANNEL_LINUX" "$ITCH_BUTLER_VERSION" "$APP_VERSION"
fi
fi
# ==========================================
# ITCH DEMO - does not auto push
# ==========================================
if [ $APP_BUILD == "all" ] || [ $APP_BUILD == "itchdemo" ]; then
echo "Building Itch:Win:Demo"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_WIN_DEMO
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchDemo -projectPath $PATH_PROJECT -buildWindowsPlayer $PATH_BUILD$PATH_ITCH_WIN_DEMO"/"$APP_NAME$APP_NAME_WIN_EXT -quit
echo "Removing PDB files.."
rm -f $PATH_ITCH_WIN_DEMO"/"player_win_x86_s.pdb
rm -f $PATH_ITCH_WIN_DEMO"/"player_win_x86.pdb
echo "Compressing Itch:Win:Full"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_WIN_DEMO"-"$APP_VERSION".zip" $PATH_ITCH_WIN_DEMO
# --------------
echo "Building Itch:Mac:Demo"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_MAC_DEMO
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchDemo -projectPath $PATH_PROJECT -buildOSXPlayer $PATH_BUILD$PATH_ITCH_MAC_DEMO"/"$APP_NAME -quit
cp "/Users/user/projectpath/builds/ScreenSelector.tif" $PATH_BUILD$PATH_ITCH_MAC_DEMO"/"$APP_NAME".app/Contents/Resources/ScreenSelector.tif"
cp "/Users/user/projectpath/builds/PlayerIcon.icns" $PATH_BUILD$PATH_ITCH_MAC_DEMO"/"$APP_NAME".app/Contents/Resources/PlayerIcon.icns"
echo "Compressing Itch:Mac:Demo"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_MAC_DEMO"-"$APP_VERSION".zip" $PATH_ITCH_MAC_DEMO
# --------------
echo "Building Itch:Linux:Demo"
cd $PATH_BUILD
/bin/mkdir $PATH_ITCH_LINUX_DEMO
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_ItchDemo -projectPath $PATH_PROJECT -buildLinuxUniversalPlayer $PATH_BUILD$PATH_ITCH_LINUX_DEMO"/"$APP_NAME -quit
echo "Compressing Itch:Linux:Demo"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_ITCH_LINUX_DEMO"-"$APP_VERSION".zip" $PATH_ITCH_LINUX_DEMO
fi
# ==========================================
# FESTIVAL BUILD -- ATTRACT MODE++
# ==========================================
if [ $APP_BUILD == "festival" ]; then
echo "Copying Attract Movie to StreamingAssets"
cp "/Users/username/projectpath/AttractMode/attract.ogg" $PATH_PROJECT"Assets/StreamingAssets/attract.ogg"
echo "Building Festival:Mac:Full"
cd $PATH_BUILD
/bin/mkdir $PATH_FESTIVAL_MAC
/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -executeMethod SRSpaceZooBuild.buildVersion_Festival -projectPath $PATH_PROJECT -buildOSXPlayer $PATH_BUILD$PATH_FESTIVAL_MAC"/"$APP_NAME -quit
cp "/Users/username/projectpath/builds/ScreenSelector.tif" $PATH_BUILD$PATH_FESTIVAL_MAC"/"$APP_NAME".app/Contents/Resources/ScreenSelector.tif"
cp "/Users/username/projectpath/builds/PlayerIcon.icns" $PATH_BUILD$PATH_FESTIVAL_MAC"/"$APP_NAME".app/Contents/Resources/PlayerIcon.icns"
echo "Compressing Festival:Mac:Full"
/usr/bin/zip -r -X -q $PATH_FINAL_ZIPS$PATH_FESTIVAL_MAC"-"$APP_VERSION".zip" $PATH_FESTIVAL_MAC
echo "Removing Attract Movie from StreamingAssets"
rm -f $PATH_PROJECT"Assets/StreamingAssets/attract.ogg"
rm -f $PATH_PROJECT"Assets/StreamingAssets/attract.ogg.meta"
fi
# ==========================================
# ==========================================
echo "Done!"
Note: The wonderful Amos from itch.io suggests pointing butler at the build output folder instead of the packaged zip to save butler from having to uncompress the zip first.
Steam Upload
The above show itch.io uploads, but can also update Steam via steamcmd:
# push to steam
if [ $APP_UPDATE_PUSH == "yes" ]; then
echo "Uploading to Steam via SteamPipe"
cd $PATH_STEAMPIPE
./steamcmd.sh +login username +run_app_build steam_script_location/app_build_123456.vdf +quit
echo "Steam Upload Complete. Remember to visit Steamworks and set build live"
fi
Helpful References
- https://docs.unity3d.com/Manual/CommandLineArguments.html
- https://docs.unity3d.com/ScriptReference/PlayerSettings.SetScriptingDefineSymbolsForGroup.html
- https://docs.unity3d.com/Manual/BuildPlayerPipeline.html
- https://docs.unity3d.com/ScriptReference/BuildTarget.html
- https://docs.unity3d.com/ScriptReference/BuildTargetGroup.html
- https://docs.unity3d.com/Manual/webgl-building.html
- https://docs.itch.ovh/butler/master/installing.html
In Closing
Hope you found this article on build script automation for Unity interesting,
Jesse from Smash/Riot