Thursday, February 16, 2017

Parta Games Tech Post #1 Automating Builds & Steam uploads with Unity Cloud Build, Jenkins and Steampipe

Intro

As our blog has mostly been focused on other things, the thought of making a tech post about a specific topic has been on mind for some time. A couple of days ago I finally got around to researching and implementing a thing I've been putting off for too long: automating the Windows build of a Unity game with Unity Cloud Build and subsequently sending the build artifacts to Steam with Steampipe using the Jenkins continuous integration server, essentially making the two servers work together to solve a problem.

Why?

I strongly believe making software builds manually starts becoming a redundant task really fast when the need arises to continuously distribute builds to third-parties, other services or for example QA. This includes the separate platform-specific builds of a single game as well as builds for libraries etc. I also wanted to automate the final step of sending binaries to a store vendor's service, in this case Steam. The sooner a build pipeline is automated the more time is saved when instead of making the builds manually the developer can focus on other things and trust that things are scheduled or triggered conveniently. Creating the whole pipeline from scratch might take a day or two at worst but I believe the patience starts to get rewarded quickly.

Services & Tools

Unity Cloud Build was selected because it removes the need for our own dedicated build servers, has a handy web-api with sufficient documentation and was very easy to set up with our existing version control solutions. It's also a no-brainer if you're making a Unity game because the service is provided for everyone. This guide is created with a Unity Plus license, but that shouldn't change anything, as the service is also provided to free version users with a lower usage priority.

Jenkins is a free & great (if not the best) continuous integration server with awesome support for especially "freestyle" builds. Freestyle essentially means I can configure a series of build steps using whatever method/script/plugin is available to me. I use it for a lot of things from automating static website uploads to creating final software distribution builds. Jenkins is very popular in Java software development and the server actually is a Java software itself (needing Java runtime to function), but don't let that scare you. It's plenty powerful, stable, battle-tested and very configurable. There are also tons of plugins for myriad of use-cases.

Guide requirements:
  1. A Unity 5.x project (source controlled, our choice is Git)
  2. No prior knowledge of Unity Cloud Build
  3. No prior knowledge of Jenkins CI server
  4. Steam developer account and working Steampipe configurations. Essentially I assume you know how to upload a game build to Steam and can publish it.

Setting up the game build in Unity Cloud Build


Start by creating a new project.


As you probably know, a Unity developer account is needed to access the Unity Cloud Build service. If you've recently created your project, chances are it already exists in the Unity projects page and you can just navigate to it and enable build service. If not, create a new project. Just make sure it uses the correct organization and references the correct project ID (the same you can see in Unity services tab).

When presented with the option, enable Unity Cloud Build

Enter the source control information and give UCB the proper rights to access it. If you're somewhat familiar with source control security, setting this up should be a non-issue.


Enter source control information


The next step is to add the new platform target. As we're automating a Steam build, win32 platform is needed. Default platform config should work, but you may need to change the executable name to something sensible. In my case the default executable name was something else and I noticed it only after downloading the resulting ZIP-artifact.


Default config with a sensible executable name
And that's it! Unity Cloud Build setup is now done and you can start the first build. For me it took a couple of tries for some reason (I guess the service needed to warm up a bit), but without changing a thing the build started working. If everything goes well you should see rows of something like this appear in the History tab:

A successful win32 build
Although setting up UCB is probably the easiest step in this guide it solves a very important problem: automating the game build from source control and providing us the build artifacts.

Testing the Unity Cloud Build API

Now that you have a working UCB project you can start querying the API for information about the build. This is a convenient way for the Jenkins build to fetch crucial bit of information: the download links to the build artifacts with proper access rights. The relatively unknown UCB API solves this problem quite elegantly.

1) First find out what your API key is. Instructions to locate it can be found in the Unity Cloud Build API documentation. Keep the key handy as you will need it later in this guide, but note that it's not public information as it allows anyone to access your Unity projects through the APIs.

2) You are now ready to query some basic information from the API. I used a terminal & CURL to get the results, but you can use the HTTP client of your choice. The following query will get you information about all successful builds in UCB (note the authorization header with the API key):

curl -H 'Authorization: BASIC YOUR_API_KEY_HERE' https://build-api.cloud.unity3d.com/api/v1/orgs/your-organization-here/projects/your-project-name-here/buildtargets/default-windows-desktop-32-bit/builds?buildStatus=success&platform=standalonewindows

The result should look something like this:
The essential part in the response JSON is the value of path links/download_primary/href. It contains the direct download URL of the main build artifact (which in this case is a ZIP-file) with AWS credentials. This is exactly what you need to have Jenkins download the data and upload it to Steam.

Setting up Jenkins CI-Server

Now that you have fetched the information available through the Unity Cloud Build API you can continue setting up the Jenkins CI Server. Jenkins is available for many server platforms. In this guide I use Ubuntu Server 14.04 64-bit for which Jenkins is directly available through the default apt package manager. For installing Jenkins on other platforms please consult the official site.

sudo apt-get install jenkins

And that's it. Jenkins is installed as a linux service daemon and is starting up. The server is used through a web-interface which should start accepting requests at http://your-jenkins-address:8080.

Setting up the Steampipe build in Jenkins

Start by clicking "New item" from the leftward menu. Type the build name and select "Freestyle project" and press OK. We will work based on the assumption that this build will be automatically triggered by the successful cloud build.

Note: The way I configure and create the Steampipe app and depot configuration files during the next step is not a perfect solution, but for the sake of this guide it was fairly quick to set up. In the future it would probably be better to pull the files from Git or similar location.

Create a new "Execute shell" build step and add the following configuration:


Next you'll fetch the latest successful build data from UCB. You've already tested how the UCB API works so it's quite easy to parse the data out of the response JSON. Groovy scripts in Jenkins builds are quite versatile so it's very convenient to have the script unzip the files too. You'll probably need to install the "Groovy" Jenkins plugin in the "Manage Jenkins -> Manage Plugins" section for the build step to appear as an option. Create a new "Execute System Groovy Command" build step and add the following script:

The final step is to let Steampipe do its magic. Create another "Execute shell" script and add the following command (where $WORKSPACE corresponds to the Jenkins build workspace folder):

/opt/tools/steamcmd_linux/steamcmd.sh +login your_login_name +run_app_build $WORKSPACE/app_build_123456.vdf +exit

Note: I was running Jenkins on Linux, so I had to log in to steamcmd manually as the "jenkins" user for it to cache the login credentials. This way you need to submit the two-factor authentication code only once and the script will be able to login automatically from that point on.

Now the build is complete. It won't trigger automatically just yet, but you can run it to make sure everything works. The script will first create the config files. Then it will download the build from UCB and send it to Steam.

Setting up webhook to trigger Jenkins build

Now that you have created the two builds that work individually, it's time to make them sing together. You'll set up a webhook in Unity Cloud Build that creates a HTTP POST request to Jenkins triggering the Steampipe-build automatically, every time the cloud build is successful. First you need to configure a couple of security settings.

Jenkins security

Install a Jenkins plugin called "Build Authorization Token Root Plugin". Do this in "Manage Jenkins -> Manage plugins" page. This plugin makes it relatively easy to give UCB access to Jenkins' REST API while using a single security token (UCB does not support HTTP authentication, which is by default needed by Jenkins).

Second, you need to configure Jenkins to receive "Anonymous" requests through the built-in REST API. Go to "Manage Jenkins -> Configure Global Security" page. If security is not enabled, you should enable it now. For the purpose of this guide, make sure matrix based security with Jenkins' user account database is used. (Access control should be secure, with user accounts only for people who need access)

The "Anonymous" user needs access to builds. Check the box labeled "Build" (can be found from the "Job" column) and then click "Save".

Build checkbox for user "Anonymous" in the lower left corner
Finally, you need to add a build-specific authentication token. Go to the build page and click "Configure". From the "Build triggers" section, check "Trigger builds remotely". Think up and enter a secure token and save the configuration.

Entering the authentication token
That's it for Jenkins. You can make sure everything works by making a POST request to Jenkins with CURL. The build should start with this:

http://your-jenkins-address:8080/buildByToken?job=your-jenkins-steampipe-build&token=YOUR_SECRET_TOKEN

Unity Cloud Build webhook

In UCB, navigate to the build's "Notifications" page and add a new webhook. Copy the previous URL, check the "ProjectBuildSuccess" event, make the hook active and save. For this guide I didn't use a secret or SSL verification.

Configuring the UCB webhook that triggers the Jenkins build
Congratulations! You've successfully automated the build pipeline from Unity Cloud Build to Steam! You can now start up the cloud build and enjoy the completely automated Steam build process! Please give feedback in the comments!

Note: After a while of using completely automated builds (that triggered every time we pushed something, however trivial) we started to feel frustarated about the amount of builds adding up to Steam. We resorted to running the Jenkins build nightly and sometimes manually when needed. To use nightly builds, the only thing you need to do is disable the UCB webhook and add a "Build periodically" configuration to Jenkins. That way UCB keeps the continuous integration running while Jenkins only uploads Steam builds every night.


Wednesday, December 21, 2016

Christmas blog post

Hi everyone, long time no blog! I've been meaning to do a writeup about our current situation for a while, but just haven't had the time or energy to do so. Now that the holiday season is approaching and things come to a stop for a couple of weeks in Finland I decided to write something.

Choppa postmortem

As it happens 2016 was the year we finally "made it" as game developers and launched our first hit game (Choppa) with over 2 million(!) downloads to date - a number that's hard to comprehend. My last blog entry is dated 31st March 2016 which means it's about three weeks before we launched Choppa on iOS & Android so I had no idea what would happen very soon. Choppa was launched April 21st 2016 during Apple's "Apps for Earth" campaign which we had no knowledge of. We of course immediately thought the game was not going to be featured anywhere because of the prominent earth stuff. Boy were we wrong and we got a "Best new games" feature from Apple in 30 countries, including USA and China. Bigger publishers had been warned about "Apps for Earth" so we got a good slot and for some reason Choppa performed a lot better than the other, more prominently featured free games that week. We got 600 000 downloads and we're #1 iPad Arcade game in many countries, including the US. If I remember correctly we also broke into the top-10 arcade games on iPhone, which is awesome considering the amount of daily downloads you need to get to be there. In a nutshell Choppa was a hit, it made some money, it has had a long lifecycle for such a tiny game (every update we've made except one has been featured in one way or another by Apple). Everything went better than expected.

Other platforms

High from the success of Choppa we also put the game on Steam Greenlight (and got through!) and we also developed an Apple TV version that has also been very well received by players since it's launch on November, 17th 2016. Steam version is still under construction, mostly because of the big changes we need to consider for not being able to monetize the game with ads and in-app purchases. We want to make a good game, not "just a crappy mobile port".

What next?

As Ville has been doing contract work for the last 6 months we've been in a kind of a standstill with creating cool updates and improvements to Choppa and so on. Our next goal is clear though: we want to start working on our next game as soon as possible! As we're completely self-funded we need to consider the time it will take to create it and plan and scope it properly so we don't run out of funds in the middle of development. It's no problem for us to do contract work for a while but we've already witnessed that it's not an optimal solution because it forces one of us to run the company by himself and as the other one doesn't have the energy to work on the game it slows things down so much it's almost a living nightmare. We're also notoriously slow at making games anyway so good planning is key. We hope to be able to shed some light to our future projects soon!

Thanks

I also want to take this time to thank everyone in the Finnish indie scene for the overwhelming amount of support, advice and encouragement we've received since we started. We couldn't have done this without you and I'm completely serious. We've learned so much stuff we couldn't have otherwise without your help. We've also met so many cool people from all around the world since we started and we're super thankful for that. We've been very budget conscious before so we've only traveled around Finland but our goal for the next couple of years is to be able to attend conferences outside Finland too and meet with even more cool people. You're all awesome!

Merry Christmas and a Happy New Year from Parta Games!

God bless you, Antti Kolehmainen, Co-Founder

Thursday, March 31, 2016

What has become of Choppa?

As you may know, 'Choppa' is our second game under the name of Parta Games and we've been quite busy preparing it for a global launch. We had a great beta testing phase and managed to soft launch the title in Australia, Canada, New Zealand and Finland already. The feedback has been mostly very positive so we're really psyched and humbled about the whole pre-launch buzz! We've also been quite surprised about the attention the game has gotten in countries we haven't even officially gone yet like China and Russia. Hopefully we get to officially launch there very soon!

I'm glad to say that the game is now feature complete. We're currently contacting people about the impeding launch (sorry, no public date yet) preparing press information, trailers and stuff like that. Exciting times for sure!

Artistic vision

We didn't really think about having a proper "artistic vision" when creating the game but at some point we realised we had one. We were inspired by the great action movies of the 80s like Top Gun, Predator or Rambo and as you might remember they were usually pretty violent. We wanted the theme and the feeling and the explosions but we didn't want to make a game about killing. So we decided to use a prototype of a chopper game we had that made you rescue people instead of shooting them and combine it with 80s rock music, Amiga-esque pixel art and explosions. So in our mind the game is kind of like MacGyver of video games where you don't need to resort to violence to save the day but you're still the coolest guy there is.

When we were showcasing the game some people pointed out that the game is a lot like the old classic 'Choplifter' and they were not wrong. It's just that we didn't even know 'Choplifter' exists so the similarities probably come from some games that are in turn inspired by it. It's a funny world.

Development and openness

So we initially talked about making Parta Games' game development a bit more open. We wanted to livestream the making of prototypes, how the game is starting to shape up, discuss about the very organic decision making process we have and stuff like that. At some point we realized we don't have the required skills and time for streaming so we had trouble finding the motivation. I have a bit of streaming experience but when you constantly feel busy it's almost impossible to see the benefits in mobile game development streams. I'm not saying they wouldn't have been beneficial but it's a bit late to dwell on that now.

What I'm trying to say is the main reason we didn't stream or make dev videos to YouTube is that our game design bloated yet and that induced busyness. Instead of making a short flappy bird-esque mobile experience we created a strange hybrid of: surprisingly-long-play-session plus tough-as-nails-highscore-system plus casual-but-configurable-experience. Toucharcade called the execution "interesting" so we'll have to see what the masses think about it.

We were initially also quite worried that someone would just outright steal the idea and since we are super slow at making games we were afraid that someone will beat us and launch the clone before us. In hindsight we were maybe a bit too early to be worried about things like that and also 'Choplifter' already existed so the idea was not that original. Live and learn.

What did we learn?

While making 'Choppa' we learned to use Unity3D a bit more effectively. We might have the courage to start calling ourselves proficient with it quite soon.

There are also lots of PR related lessons we have learned since 'Go! Go! Meatball' was launched last year. We still feel a bit uncomfortable with PR but we're learning. Bear with us!

We learned how to make trailers and videos without getting super angry at the tools. We haven't learned how to not get super angry at each other yet but we're getting there!

Ville always says that the best way we can learn is launch the game and see what happens and while I have launched many games and totally agree with it I'm still the one who usually wants to keep polishing the game until it cracks or just burts on fire from the friction. I just don't want the game to go out looking like crap or feeling broken because I'm so afraid if the FTUE is bad the game will be abandoned. I have realized my thinking is a bit outdated because mobile games currently are very iterative and especially soft launch can be used kind of like "Early access" in the PC side to tweak the game closer to what potential players like the most.

Anyways I hope I have the and energy to write a postmortem after we get some perspective from the global launch.

God bless you, Antti Kolehmainen, Co-Founder

Sunday, October 25, 2015

Go! Go! Meatball Postmortem

This is Parta Games' first blog post. It's kind of weird to write the first entry during one of the biggest letdowns in my recent memory. I would've liked to write something more positive at first - like hype our next game - but I guess that will have to wait. I'm going to write about our first game release. If my writing seems a bit bitter you are not completely wrong, but my general feeling is still that we got lots of valuable things from this release. Tons of important lessons and lots of experience was gained. Our next game will be and do better! Sorry about the lack of jokes! I'll try to add more next time.

The game and the launch

The game was slated to be released on August 10th. We had announced the release date in many places but we failed to launch because of some App Store approval hurdles. Missing the mark was not that big of a deal to us, we got some good press in Finland. A local magazine wrote about us, YLE (one of the biggest Finnish media houses) made a story about us and it went on local radio, local TV news and the internet where the story reached a lot of people in Finland. It was very exciting! We used every possible social media outlet, contacted every press we could, offered review copies and not counting YLE and local papers - were met with almost universal disinterest. The games press didn't seem to care about our game.

We were super excited that Indie Game Magazine published some news about our upcoming release a couple of weeks before the release and offered to maybe even review the game! We were super thankful... but it seems to have fallen through because we've not heard of it since. We were so thirsty for reviews that even a bad review score would've sufficed. We learned that in the current mobile scene no one wants to review bad or mediocre games. There is no such thing as a bad or mediocre review score or verdict for a mobile game because - to put it bluntly - no one pretty much cares about anything else but the next Angry Birds. That's to be expected when you realize the MASSIVE amount of apps submitted to the App Store every day. You can't afford to go through the garbage. At that point we weren't part of that garbage in our mind.

Our press releases weren't all for naught, though. Before the Android release we'd been noticed by droidgamers.com and techcrunch.net which made us really happy. We managed to not be invisible even though it currently feels a bit like it. Unfortunately not much of our press has translated into actual sales. Same goes for our small Facebook ad campaign that didn't translate into any sales even though we got hundreds of clicks. Bummer.

Go! Go! Meatball was released August 14th on the App Store, only 4 days late and only a couple of months after we started working full-time at Parta Games. We were at the top-10 of the Finnish App Store for a week and got really excited. We were at the top of the paid iPad games category after all! After the sales figures started updating, we learned the brutal first lesson of App Store popularity: you can get to the top of many smaller countries' App Stores top-lists with only a couple of premium sales. Sure, we had an initial sales burst, but it was small: about 20-30 copies which turned out consist of mainly friends and family members. Not many others seemed to buy.

Currently the game has sold under 100 copies after two months on the App Store and a month on Google Play. At this point I can pretty safely say the game will never make ends meet and I have doubts if it will even have any cross-promotion opportunities for our future games. Maybe if we release it for free some day... dunno. When we calculated our company's finances we thought that 2000-4000 sold copies would be enough to fund some of our future games' development. The reality is unfortunately a bit different. It's a huge disappointment, honestly.

Development

We'd been making the game by the two of us for over a year in our spare time and despite our best efforts to keep the game small, it grew bigger than we imagined. In man hours we probably didn't invest that much into the game but when we take the time interval from the first prototype commit to the last before the Android release... the game took almost 4 years to make. You can't make a game on and off for 4 years and not let it grow on you and become a part of what you are.

You must be tempted to as what took us so long. It's not that big of a game?

Originally the game was supposed to be a lot bigger: a game with an actual story (albeit as mindless as the current revision). It was supposed to be a puzzle platformer with autorunning mechanics: touch an object to change the level so you can go forward, solve a couple of puzzles in the way... things like that. It went through couple of revisions under my care and at some point I realized I can't finish it alone since I've been developing it for 2 years without much actual progress.

Then I brought Ville along. We were two old friends dreaming of our own indie game studio since the last century so we thought why the heck not just release this game and start a company. We designed the game from scratch as an endless runner game and started working on it in our spare time, one day a week. I guess my old ideas of a bigger game were too persistent and the game design kept ballooning from every corner. After a while the game had become what it currently is, a non-endless runner platformer game with handmade levels and handmade engine.

So yeah... it took us way too long, the game is not that big and we tried to scope it even smaller, but failed. We removed things that should've not been removed, added things that should've not been added, scoped from the right and the wrong place. The end result is a bit of a mess design-wise. It tries to be something of the original vision but isn't, it tries to be an endless runner and it isn't that either. The biggest struggle was adding content to the game and on hindsight we should've hired a level designer because at least I personally wasn't up to the task. Also the tools and the failed scoping made creating levels a chore. If you don't have fun creating levels for your own game people will not have fun playing them.

We we're also too arrogant in that we wanted to create a nostalgic old-school game with modern mobile mechanics that ALSO has nostalgic old-school business model. Go! Go! Meatball is premium game and we have learned the hard way that your game has to be truly exceptional before people are ready to pay for it upfront. Maybe we would've done better if we went for F2P and in-app-purchases. Maybe not. When I was a kid my mother said that making games is not a real job. I think what she would say today that making premium mobile games is not a real job but F2P is. A little joke there.

End result

All joking aside, the end result is a game that doesn't sell but of which we are nevertheless proud of. We made it completely by ourselves, created our own engine, made all the graphics, music and content and even self-published the game. We think it's a good debut game.

I think it's important to write about failures in the industry that mostly celebrates massive successes. We're not going to give up, and we already have a couple of really cool game projects under construction. Our goal is to be a bit more open with our next projects so stay tuned for twitchy streams and developmenty blogs!

God bless you, Antti Kolehmainen, Co-Founder