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.

unity_travis.png

 

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.

travis_add_repo.png

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.

travis_flip_switch.png
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.

find_the_hash.png

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.

Erik Rahtjen

Software Engineer at Stable Kernel

  1. Chris B

    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

Leave a Reply to Chris B Cancel reply

Your email address will not be published. Required fields are marked *