Half a year ago GetSocial Mobile team released SDK v.3.0 with a lot of new cool features and breaking changes from 2.x version. Since then, I’ve joined GetSocial and have had an opportunity to make a complete revamp of their Unity SDK. In this series of posts, I’ll describe what decisions we made and what challenges our team faced with developing the GetSocial Unity SDK.

Approaches in building Unity SDK

First, we needed to decide which approach to go for in order to create an SDK. At that moment, we had Android SDK written in Java and iOS SDK in ObjectiveC, both completely native to achieve the best performance and user experience. Unity supports three scripting languages: C#, UnityScript (aka JavaScript), and Boo. We decided to expose API in C# as it’s the most widely used one. Let’s check which options we had to achieve the goal…

Pure C# SDK

This was the best approach from developer and user perspective as;

  • It delivered the best performance;
  • It was simple to setup;
  • We could make SDK available to 21 platforms supported by Unity.

It seemed like an ideal solution, but there were few huge disadvantages:

  • At the end we would have had a third huge codebase that should be kept in sync with iOS and Android ones;
  • All UI would have been reimplemented in C#, not an easy task as games use different UI frameworks.

Cross-compilation to C#

According Google report, that they managed to reuse 70% of code between Android, iOS and Web Inbox clients, we were so impressed by the idea that decided to give it a try. Because of similarity between Java and C# we digged in a direction of recompiling Android SDK to C#. From a positive side, we found that:

  • There are tools for cross-compilation like Java Language Conversion Assistant from Microsoft;
  • In theory, in the end we would get C# library, that is fast;
  • And possibility to use on all Unity supported platforms.

On the other hand:

  • It was not possible to cross-compile presentation layer as it uses Android APIs. That means we would need to replicate the UI part of the SDK manually on C#;
  • Cross-compilation required a clear separation between business and presentation logic, which would lead to a huge refactoring in Android SDK;
  • It would be hard to establish automated C# SDK regenerations when Java source is updated, as cross-compilers produce upgrade issues that should be fixed manually.

Unity native plugin

Native plugins are platform-specific native code libraries. They can access features like OS calls and third-party code libraries that would otherwise not be available to Unity.

Pros:

  • Very few code needed; a bridge is a thin adapter layer between API exposed in C# and native SDKs;
  • 100% code reuse from native SDKs;
  • UI rendering is handled by native side => no problem with variety of Unity UI frameworks.

Cons:

  • We’d be able to deploy only to iOS and Android Unity games;
  • Native SDKs API should be in sync to avoid huge amount of adapter’s code in a bridge;
  • Unity Java Native Interface implementation has issues (Unity engineers fix them quickly but tend to add a new one on each release).

Selected approach

We decided to go with Unity native plugin approach as it required the least effort, gave plenty of advantages and flexibility. Now GetSocial Unity SDK has the following architecture:

challenges-in-building-unity-native-plugins-intro-sdk-architecture

Between C# API and native libraries, we have a bridge layer on Unity and native side. The main task for the bridge is to invoke methods between platforms and convert data to primitive types as we can’t pass objects between platforms. To communicate between C# code and native side, Unity exposes a wide variety of APIs. On Android: Unity Messaging (the one we use to send messages between GameObjects) and wrappers around Java Native Interface. On iOS, we can invoke extern methods from ObjectiveC and use MonoPInvokeCallbackAttribute to call C# methods from the iOS world.

Everything is simple, right?

The theory is simple: thin bridge layer; few calls between C# and native platforms; nice demo app and problem solved. But a simple solution doesn’t come without any challenges. Here are a few of my favorites:

  • Performance: potentially bridge could become a performance-wise bottleneck, especially if calls will be made on each frame (keep in mind 16ms rule);
  • Testability: with Unity native plugin approach most of the SDK will be in the native code, that means we can test only on iOS or Android device/simulator, but not Unity player;
  • Continuous delivery: SDK consist of 3 parts, each one has it own build process, setting up build pipeline could be complicated;
  • Version fragmentation: Unity is a very dynamic platform, each release brings tons of cool features and … new bugs. Unlike game developers who can select Unity version and use it during whole game life, we have to support all Unity versions starting, at least, from 4.1.

vitalik

Want to know more?

This was the first post from the Mobile team, and we’d love to know what you think. Don’t hesitate to share your thoughts and experiences with building Unity plugins in comments. Follow GetSocial on Twitter and Facebook to stay updated!