Unity is a cross-platform game engine which has risen to prominence as the go-to engine for indie game developers. Coming from the world of application development, I’ve become quite enamored with process. Specifically, I have become enamored with good process. In software development of any kind, certain aspects are both highly error prone and tedious. This is where continuous integration for Unity comes in.
Some Information Before We Start
This example was written using Unity 5.5.1f1 on macOS. For source control, I use Github and you will need an account to follow along. The continuous integration service we will be exploring is the much loved TravisCI. Travis integrates directly with Github and setup is a breeze.
Getting Started with Github
Go ahead and create a new Unity project or load one of your pre-existing games. For this project, I have created a new game called TravisCI test.
Our game will have one scene named Main
with the TravisCI logo attached to it.
After this, we have to initialize a new Github repository for holding our game. On Github, create a new repository named travisci-test
and then in your terminal, navigate to root directory of your Unity project and follow the Github instructions for creating a new repository:
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:<YOUR GITHUB USERNAME HERE>/travisci-test.git
git push -u origin master
After achieving this groundbreaking result, your Github repository should have everything you need inside of it.
Word to the wise: You might want to be careful pushing your entire repository up to Github. Many parts of the Unity platform can be safely ignored and regenerated and are better off not in source control. Read more about the ideal .gitignore for Unity before configuring your production game with Github.
Configuring TravisCI
If you have set up your project using a public Github repository, this part will be a breeze. If you are using a private Github repository, then you will need to pay to use travis-ci.com. For the purpose of this article, I am assuming you chose the free option. Just hit Signup using Github
and you should be brought to the dashboard. On the left of the page, hit the +
next to My Repositories
.
From here you will be shown a list of public repositories you have. If you have been keeping up, you should see <YOUR GITHUB USERNAME>/travisci-test
in the list. Flip the switch to on to start your continuously integrating adventure.
Congratulations! Just kidding, you have more to do, but wouldn’t that have been nice?
Next up, we have to configure your build using the .travis.yml
file, which tells Travis what it needs to do in order to build your application.
Time to get started. Create your config using touch .travis.yml
. In your favorite text editor, alter the config file:
language: objective-c
osx_image: xcode8.1
rvm:
- 2.2
before_install:
- chmod a+x ./Scripts/install.sh
- chmod a+x ./Scripts/build.sh
install:
- ./Scripts/install.sh
script:
- ./Scripts/build.sh
There are two scripts specified here to be run during the install and build phase. The config file is saying we want to use Mac, we have two scripts, before you run them make them executable, then go ahead and run them in the right order.
Related: Piloting Life in the Fastlane
Installing Unity on TravisCI
Let’s get into the meat of the problem. First, we have to inform Travis that it needs to prompt a download of the macOS version of Unity in order to build the project. Additionally, you need to tell it to install the build tools for any platforms you want to install for. In our case, we will target the major desktop audiences and build for Linux, macOS and Windows.
The trickiest part of this entire process comes from the way Unity packages their releases. The downloads are hidden in a hashed folder. In order to find the current version (5.5.1f1), I had to go to the Unity download archive and inspect the network response from clicking Downloads (Mac)
-> Unity Editor
and checking the request URL.
In this case the hash ended up being 88d00a7498cd
which you can see in the response URL https://netstorage.unity3d.com/unity/88d00a7498cd/MacEditorInstaller/Unity-5.5.1f1.pkg?_ga=1.171700002.326332384.1483170008
.
Now onto your install.sh
script. Create the file, as before, and alter its contents:
#! /bin/sh
BASE_URL=https://netstorage.unity3d.com/unity
HASH=88d00a7498cd
VERSION=5.5.1f1
download() {
file=$1
url="$BASE_URL/$HASH/$package"
echo "Downloading from $url: "
curl -o `basename "$package"` "$url"
}
install() {
package=$1
download "$package"
echo "Installing "`basename "$package"`
sudo installer -dumplog -package `basename "$package"` -target /
}
# See $BASE_URL/$HASH/unity-$VERSION-$PLATFORM.ini for complete list
# of available packages, where PLATFORM is `osx` or `win`
install "MacEditorInstaller/Unity-$VERSION.pkg"
install "MacEditorTargetInstaller/UnitySetup-Windows-Support-for-Editor-$VERSION.pkg"
install "MacEditorTargetInstaller/UnitySetup-Mac-Support-for-Editor-$VERSION.pkg"
install "MacEditorTargetInstaller/UnitySetup-Linux-Support-for-Editor-$VERSION.pkg"
Basically, it’s a pretty simple script I found on Github and subsequently updated. It runs the install()
function for Unity and all the support files for building for Windows, Mac and Linux as Unity is no longer bundled with those tools. install()
then calls download()
which, as you might suspect, downloads the packages using curl
. After it has finished downloading, it runs the installer to install unity and the build tools.
Related: Continuous Delivery for Android (Part 2)
Making the build on TravisCI
As before, you will need to create build.sh
:
#! /bin/sh
project="<YOUR PROJECT NAME HERE>"
echo "Attempting to build $project for Windows"
/Applications/Unity/Unity.app/Contents/MacOS/Unity
-batchmode
-nographics
-silent-crashes
-logFile $(pwd)/unity.log
-projectPath $(pwd)
-buildWindowsPlayer "$(pwd)/Build/windows/$project.exe"
-quit
echo "Attempting to build $project for OS X"
/Applications/Unity/Unity.app/Contents/MacOS/Unity
-batchmode
-nographics
-silent-crashes
-logFile $(pwd)/unity.log
-projectPath $(pwd)
-buildOSXUniversalPlayer "$(pwd)/Build/osx/$project.app"
-quit
echo "Attempting to build $project for Linux"
/Applications/Unity/Unity.app/Contents/MacOS/Unity
-batchmode
-nographics
-silent-crashes
-logFile $(pwd)/unity.log
-projectPath $(pwd)
-buildLinuxUniversalPlayer "$(pwd)/Build/linux/$project.exe"
-quit
echo 'Logs from build'
cat $(pwd)/unity.log
echo 'Attempting to zip builds'
zip -r $(pwd)/Build/linux.zip $(pwd)/Build/linux/
zip -r $(pwd)/Build/mac.zip $(pwd)/Build/osx/
zip -r $(pwd)/Build/windows.zip $(pwd)/Build/windows/
This script runs the unity editor without graphics and says, “Build our app for XYZ platform.” That’s it, nothing too special. It’s the command line equivalent to using the editor and running a build from the menu. After that, it zips the relevant build output for each platform in preparation for deployment.
Now, you have successfully created an environment for continuous integration for Unity using TravisCI!
Deployment (optional)
One of the nice things you can do with Travis is automatically deploy your application. For example, you could automatically deploy to a Heroku server. In our case, we want to upload the build to Amazon S3 cloud storage. This way, we can manage its releases and even provide a download link to any users we may have. Or we could use it to set up a “nightly” build to showcase any current work being done. I’ll leave coming up with use cases as an exercise to the reader.
You will need an AWS account with S3 and access to your AWS access key and secret. If you do not have this it will cost money, so this is an optional exercise for the reader.
Go to your TravisCI settings page for your repository. We are going to add your AWS secret and key here under the names ACCESS_KEY_ID
and ACCESS_KEY
respectively, as environment variables.
Amend .travis.yml
with the following appended:
deploy:
provider: s3
access_key_id: $ACCESS_KEY_ID
secret_access_key: $ACCESS_KEY
bucket: <YOUR S3 BUCKET>
local-dir: Build
upload-dir: <THE DIRECTORY IN THE BUCKET TO PUT BUILDS IN>
skip_cleanup: true
In addition to assuming you have an S3 account, I am going to assume you know how to use S3 and have set up a bucket with a directory for storing your builds.
Hi,
Is there a license for these scripts you’ve provided? I’ve tweaked them pretty heavily to work with Jenkins and was considering throwing up the scripts and Jenkinsfile on a Github repo (with a link to this article) but only if you’re okay with that
Thanks
Hey Chris!
Feel free to use or edit anything to the repo, and Erik will make sure the license reflects that on GitHub. Have a good day!