Sponsored By

Porting 80 Days from Native-iOS to Unity

My experience porting 80 Days from iOS (Native) to Unity for release on PC and Mac.

Ben Nicholson, Blogger

November 24, 2015

6 Min Read
Game Developer logo in a gray background | Game Developer

[The original blog post of this content is here]

While first getting started with Cape Guy, I also discovered 80 Days on my iPad. I absolutely loved it and, after a surprising response to a tweet, discovered that Inkle were also based in Cambridge (UK). I already had plans for a first project but, having recently read The Lean Startup, was willing to pivot early, in this case before even actually starting in the first direction! Now THAT’s what I call being agile!

I’d always planned on building up a series of increasingly ambitious projects using Unity, which I’m still doing, but saw an opportunity for both Inkle and Cape Guy. I emailed them and we met up in the pub a few days later. It turns out that Jon and Joe are both really great guys and we got on straight away. An hour or so later we were discussing me doing a PC and Mac port of 80 Days, using Unity. Inkle could release a game to the PC market – which they’d been considering doing for a while – and I could get comfortable using Unity while not having to worry too much about game design (one step at a time!)

Let’s DO THIS!

We agreed that I would do the vast majority of the port myself, but that Joe would take ownership of the C# backend for Inklewriter and the story view. Later on in the project, Inkle also hired Tom Kail who took on the front-end UI work for the conversation and market/luggage view. In exchange I trained him up in the ways of a games developer. It was a bit like Yoda and Luke, only I’m not a Jedi Master :-(, and we weren’t in a swamp :-).

At the start of the project, I was looking through the codebase for the iOS version and doing some rough calculations on how long it would take to do the port. I came up with an estimate of around 6 months. To anyone with experience developing games, it will come as no surprise to hear that the port actually took 11 months. As experienced as I am in the games industry, I still under-estimate by a factor of about two wherever there are unknown factors.

For this project the unknowns were:

  • I had only a passing knowledge of Objective-C (which the iOS version’s codebase is written in)

  • I was only really getting started learning Unity and I had not yet done any production C# coding, just hobby coding (my previous jobs/projects have been mostly C++ based)

  • Unity were working on their new UI system but it wasn’t out yet and they hadn’t announced a release date. 80 Days has a lot of complex UI in it.

Deciding What to Port and What to Rebuild

Being Apple platform developers, Inkle used the MVC pattern pretty heavily. As a general rule, I straight ported the model and controller parts directly while reimplementing the view parts using Unity features and enhancing them where possible. However, in some areas, I reimplemented all of a system where I felt it could be significantly simplified.

The game is ‘view heavy’ however, so in the end Joe, Tom and I rebuilt a large chunk of the game using Unity features (in Unity’s new UI). It’s not as simple for complex UI as the linked video there suggests, but it is an incredibly powerful UI backend.

Porting Objective-C to C#

I started off doing the port by hand, which allowed me to get accustomed to the syntax of Objective-C. Though I never intended to do the whole port like that, it was a good way for me to get acquainted with the language as well as getting used to Joe and Jon’s individual coding styles. While doing that I was also looking for ways to automate, at least some of, the process. The best solution I found was to do a first pass conversion on the code one file at a time using a tool called Automagical. After which, I would go through and fix up all the references and any code that Automagical couldn’t interpret.

If I was starting the project from scratch I would probably try to do the first pass automated conversion of the entire project using Automagical, or a similar tool, as a single project. I would then split the game into sections which can be integrated and tested individually.

That process would have taken a lot more time up-front. Automagical is really great at syntax conversion but isn’t very good at interpreting the semantics of the code. A programmer is required to stitch the resulting code back together. It’s also actually quite poor at handling code comments in some places (I had to reformat most of the commented enums in the game prior to conversion). If you want to know more, take a look at the information available on Automagical’s site. However, once this initial conversion is done, I think the route to a working game would have been a lot shorter. The non-C++-like function call/message passing syntax in Objective-C really does make conversion by hand a laborious and error prone process. It’s also exactly the type of thing computers are really great at!

This automated approach to conversion would lead to a codebase which isn’t really understood by anyone though and it would have been harder to make any large scale changes like I did during conversion. A lot of the rendering and route generation code has been improved and most of the views were rebuilt with a more PC friendly interface. Most of the immediately visible changes could have been applied after the conversion. As for which approach would be ultimately faster, I’m not sure. The main draw towards the approach I actually took to the port is that I could integrate systems one at a time and use an automated testing framework, which I wrote while learning Unity, to ensure that things worked and were tested as we went along. I was also still able to use Automagical on sub-sections of code which then had to be plugged in to the existing code where interfaces had been changed etc.

A special note for my arch nemesis (during this project). In Objective-C, passing a message to a null receiver simply does nothing while in C Sharp calling a method on a null reference throws an exception. This behaviour difference between the languages led to the vast majority of the bugs I had to fix during development. The fix is easy of course, just wrapping the call in a not-null check, but it’s not always obvious which calls require wrapping from the context.

Summary

Overall, I think this project was a success. It was a fun project to work on and we saw steady progress throughout the project (it was clear that it was going to take longer than my initial estimates early on in the project) and the final product is a great port of a great game. There is more information about the game and the reviews it received here or you can just watch my favourite one of all:

 

Read more about:

Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like