Bringing native iOS frameworks into Unity games !

sarra srairi
Voodoo Engineering
Published in
7 min readJul 16, 2020

If you work in the same field as I do, you know how difficult it can be to insert features — whether its ads or rewards or any other customised features — from various different sources into various different games, seamlessly and fast. This can lead to huge compatibility issues that need effective and efficient solutions.

At Voodoo not only do we know how to make games but we also know how to make different programming languages and environments talk to each other!

Let’s take a look at how to add native functionality to our Unity games!

A Tale of Two Methods…

Wrapping and Swizzling, two different methods for two different reasons …. Let’s talk about adapting native iOS SDKs for Unity.

Wrapping an iOS native SDK for Unity

Facebook Square Placement project

Let’s take the example of integrating Facebook interstitial video into our Sweet Square Placement (Unity UI), by using the native Facebook Audience Network in our Unity game. We have some serious compatibility issues to resolve…

How do we proceed ? Maybe you’ll say just add the SDK dependencies and call the DisplayInterstitial()method and that’s it!
Right ! but all of our games are developed in Unity and even the square format is a Unity prefab. So how can we integrate video into it from a native SDK ? Therein lies the rub!
The solution is to wrap the native Facebook SDK for Unity!

Swizzling iOS method!

SplashScreen Ad project

Now, for our purposes, let’s say we want to customize the game’s splash screen behavior in Unity.

The Xcode native project will be generated by Unity with all the required libraries, precompiled .NET code and serialized assets.

So the whole splash screen process is redefined by the Unity engine, which is not accessible from the c# part and this requires us to create some specific native logic.
Taking into account all the disadvantages and side effects of possible solutions in this scenario, we can make the decision to…

use the Swizzling method…
When I say “swizzling”, I mean the act of replacing the original method with our own bespoke method.

Who usually uses this method?

The gaming industry is the ideal market for advertising. so most Ad Networks/Monetisation solutions (eg: Facebook, Applovin ..Mopub.) use this SDK wrapping method to adapt their pre-existing native SDK to Unity/C#.

Concerning Swizzling, most of the usage will be to extend the functionality of an existing method or to override default behavior. So subclassing would be the most preferred way to do the job, and for most scenarios, it probably does the trick.

As @mattt said in nshipster : “swizzling is widely considered a Voodoo technique prone to unpredictable behavior and unforeseen consequences.”

I would say 99.999% of the time we avoid using this in our frameworks, as it is a potentially useful but also particularly dangerous approach. That said, it’s safe if we use it properly and I will explain how we can do so later. Because swizzling is not an Atomic Method, it can definitely be difficult to understand and debug.

In some cases using swizzling can be the simplest solution, e.g. when Apple forgets a super call :D ! or if we need to do some tricky overrides in app delegate using Unity for iOS.

Case Study

A tip: only use this method if you need to, it is not worth doing it for kicks.

Here are the key steps to integrate a Voodoo-native Framework in Unity games using a C# wrapping solution

  • Unity part: The Unity project (in our case — the game)
  • Wrapper part: To communicate with the native SDK, we need to build a bridge between the Unity C# and the native code, using C++ (.cpp) or Objective-C++ (.mm)
  • Native part: the framework or code to inject

Step 1

Let’s start by creating a new framework in Xcode (Swift or Objective-C). In the same workspace, add your native test application. Try to reproduce the Unity behavior needed in the test app.

Validate all the framework tests. The framework should respond to the use case exactly.

N.B.: the String values returned from a native method should be UTF–8 encoded — and allocated on the heap

Add a new CocoaTouch class that looks like this:

VoodooFoo.swift

For this example you can use your framework/framework.h header file to add the C code
We need to use it for bridging

#ifdef __cplusplusextern “C” {#endiftypedef void (*RequestFooCallback)(const int status);#ifdef __cplusplus}
#endif

Step 2

Now create your Podspec Repository on Github and generate the framework using Cocoapod dependencies

Pod::Spec.new do |s|s.name             = 'framework name's.version          = '1.0.0's.summary          = 'Detect if user is European and present GDPR modal if needed's.description      = <<-DESCDetect if user is European and present GDPR modal if neededGDPR text versioningPlug your custom view controller in GDPRService setup to have control stylingDESC
s.homepage = 'https://www.voodoo.io's.license = { :type => 'MIT', :file => 'LICENSE' }s.author = { 'Sarra Srairi' => '' }s.source = { :git => 'git@github.com:"framework link"', :tag => s.version.to_s }
s.ios.deployment_target = '9.0's.swift_version = '5.0's.frameworks = 'AVFoundation', "Other Framework" 's.static_framework = true
framework = s.names.source_files = [ "%s.framework/**/*.{h,m}" % [framework] ]s.preserve_paths = "%s.framework" % [framework]s.public_header_files = "%s.framework/**/*.h" % [framework]s.vendored_frameworks = '%s.framework' % [framework]end

Unity

Use Play Services Resolver to handle the dependency management. then add the dependencies on Unity as an Xml file.
This file should be in Unity project/Folder/Editor/fileNameDependencies

XML dependencies

Step 3

Create a (.mm) file to build a bridge between the Unity C# and the native code add this file to your Unity folder with the framework ressources.

Bridge Objective-C ++

Step 4

Integrate this whole package into Unity. Add the C# interface to communicate with the native methods that we will create below

UnityProxy.cs (Unity C#)

Tips : To make it easier to debug, wrap your native methods with an additional C# layer Once those 3 steps are done, you can build and run your final project In Xcode.

Using Swizzling methods in Objective-C

How does swizzling work in order to customize the splash screen generated by Unity without changing the user experience? (example of the splash screen that we mentioned at the beginning of the article)

The first important point was to find the reference class that orchestrates the splash screens in Unity. As far as our example is concerned, it was the SplashScreenController, generated by Unity. Now we’ll change the create() method behavior and customize it to our needs .

1- Start by creating a category of the class to update its functionality. Let’s create SplashScreenController.mm

#import “SplashScreenController+Native.h”@implementation SplashScreenController (Native)@end

2- Add updated functionality

- (void)swizzled_create:(UIWindow*)window {// your code here}

3- Import ObjectiveC runtime, using the following code #import <objc/runtime.h> Here we’ll implement the +(void)load. method as below and change methods using a function from the Objective-C runtime library

+ (void)load {// 1: Swizzle should be done in dispatch_oncestatic dispatch_once_t once_token;dispatch_once(&once_token, ^{// 2: Get the compiled selector namedSEL originalSelector = @selector(create:);SEL swizzledSelector = @selector(swizzled_create:);// 3: Return a specified instance method that corresponds to the implementation of the selectorMethod originalMethod = class_getInstanceMethod(class, originalSelector);Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);// 4 : use method_getImplementation() to get the pointer that points on the start of the function of our swizzled method -- 
BOOL didAddMethod =class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
// Call the class_addMethod() which is adding a method on a class at runtime and returns a boolean if the “add procedure” was successfulif (didAddMethod) {class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
// 5: Methods are swiped using function from Objective-C runtime library. Method_exchangeImplementations changes the implementation of two methods method_exchangeImplementations(originalMethod, swizzledMethod);}

Selector is a C string that represents the name of the method at the runtime. we are getting the selectors for the two methods that we need to swizzle.

Method is an entry to the dispatch table of the class, which maps the Selectors, with their Implementations. so we are getting a reference to the methods that we want to swizzle later.

You can customize the splash screen behavior using the swizzle method — add this file into your Unity project once the project is built and then run it in Xcode you’ll see the results.

I typically do not recommend using this method for production code, except as a last resort, but I must admit it’s very useful to explore Apple’s framework.

As I’ve mentioned before, when considering using the swizzling method, be sure to assess all its disadvantages before you get started, it can save a lot of time and heartache.

A lot of the time we feel like real overlay hackers at Voodoo!!
We’d love to hear any other ideas and solutions you guys might have to solve these issues… don’t hesitate to reach out to us to discuss any ideas you might have.

--

--

sarra srairi
Voodoo Engineering

Senior iOS Software Engineer! Video Game Lover 🎮, Music Addict