HowTo: native iOS plugins for Unity3D

Here at TWNKLS, we are used to develop in many different programming languages and platforms. One of the platforms we use a lot is Unity3D.

When developing a new mobile application, we would often see a need for custom mobile logic that Unity3D does not support out of the box.
Actions like taking a picture and saving it to the camera roll or even sending an in app email would fit the “custom mobile logic” description and would thus be build as a native plugin. So how is a native plugin built you may ask? Well, that’s exactly what this article is about!
In this article I am going to take you through the steps of building a native mobile compiled plugin for use in Unity3D.

When talking about mobile development, we generally mean 1 of 2 platforms.
Namely iOS or Android.
Let’s start with iOS.

1. Toolset

  • An Apple computer.
  • XCode IDE.
  • An Apple device to compile on (also Apple simulators).
  • Objective-C coding knowledge, as I am not covering the language itself.

2. XCode project setup

A. Open XCode and create a new iOS static library project.


B. Give your plugin a name and namespace.
Namespaces generally follow these rules : Domain – Company – PluginName


C. Finish the project creation process.
Your project structure should look like the following:


The files in red indicate that those files are not yet valid.
For now, don’t worry about them. We will cover them in a later stage.

3. The Objective-C part.

Now that your project has been setup correctly, let’s dive into some objective-C code. A typical Objective-C class has 2 components, a header (.h ) and a body (.m) file. We will start with our header file.
The header file is typically viewed as an “interface”, defining parameters and methods.

//import the basics.
#import "Foundation/Foundation."

//start interface.
@interface MyNativePlugin : NSObject  //extend from basic object.

//define variables.
@property ( retain, nonatomic ) NSString* dummyString;

//define methods.
-(id) init;
-(void) doMyNativePluginStuff: (NSString*) passed_name;

//end interface. 

In the piece of code described above, we define an interface called “MyNativePlugin.h” which has two methods, namely “init” and “doMyNativePluginStuff”.
The first accepting no parameters and the latter accepting one string parameter. The interface also defines a class variable called “dummyString” of type NSString.

Next up is the corresponding body file.
A body typically incorporates the variables and methods defined in the header.

//import the header file.
#import "MyNativePlugin.h"

//start implementation.
@implementation MyNativePlugin

//synthesize variables.
@synthesize dummyString;

//define methods.
-(id) init {
   return self;

-(void) doMyNativePluginStuff: (NSString*) passed_name {
  //Do something with the passed name.
  //Here we just log the passed_name
  NSLog( @"%@", passed_name );

//end implementation.

That’s it for our plugin code.

Next step is to setup a connection point for Unity3D with which it can communicate with our code. This is typically done through the UnityAppController. When Unity3D creates a XCode project, it creates a main entry point for the Objective-C application. This entry point is the UnityAppController.

There are multiple ways to make the connection with our plugin:

  • Subclass the AppController
  • Inject code at compile time through Post Process Build scripts.
  • Open the UnityAppController and hand-code your custom code inside.

Our goal is to get our class initialized on start-up AND call our class after some unity event.
We could open the UnityAppController files and code our initialization and implementation code inside of these files. But the downside is that every time Unity3D builds ( or replaces ) a new xCode project, you will have to do this manual coding stuff again…. and again…. and again.

We definitely need something more robust and automated.
What we need is to subclass the UnityAppController to keep all unity generated codes but easily implement our own.

IMPL_APP_CONTROLLER_SUBCLASS is a method that will take a class as parameter, subclasses it from UnityAppController and make it the new AppControlller being called by Unity3D as entry point.
For this to work we need to make our own UnityAppController implementation with our codes.
This can be fairly simple.
Below a quick 1 file implementation of an AppControlller subclass (header and body in 1 file )

#import "MyNativePlugin.h" //our newly made plugin.
#import "UnityAppController.h" //our link to the base class.

//------- start header ----------------
//start interface.
@interface MyNativePluginAppController : UnityAppController  //extend from UnityAppController.

@property ( retain, nonatomic ) MyNativePlugin* myNativePlugin;

//define methods.
-(void) initNativePlugin;
-(void) doCallNativePlugin:(NSString*) name;

//end interface.

//------- start body ---------------
@implementation MyNativePluginAppController

//synthesize variables.
@synthesize myNativePlugin;

// overriding main unity entry point.

-(void) startUnity: (UIApplication*) application {
   [super startUnity: application];  //call the super.
   [self initNativePlugin];          //call method to initialize our plugin class.
-(void) initNativePlugin {
   myNativePlugin = [[myNativePlugin alloc] init];  //initialize our plugin class.

-(void) doCallNativePlugin:(NSString*) name {
  [myNativePlugin doMyNativePluginStuff:name ];  //call plugin


//setting this as app controller.

Save this file as

A small recap of what we just did.

  1. We created a class to hold our custom plugin code called MyNativePlugin.
  2. We created a main entry point which subclasses UnityAppController and initialises our plugin class on start-up called MyNativePluginAppController.

Let’s continue our journey.

4. Building the connection with Unity3D.

In order for Unity3D to call our Objective-C, we will need something that is called an “ extern C ” method. This method defines a method which will be exposed externally and can be called from Unity3D. Because our flow goes from Unity3D to Objective-C, this method will need to be in our Objective-C entry point, thus the needs to be modified to have such a method.

//import the basics.
#import "MyNativePlugin.h" //our newly made plugin.
#import "UnityAppController.h" //our link to the base class.

//------- start header ----------------
//start interface.
@interface MyNativePluginAppController : UnityAppController //extend from UnityAppController.

@property ( retain, nonatomic ) MyNativePlugin* myNativePlugin;

//define methods.
-(void) initNativePlugin;
-(void) doCallNativePlugin:(NSString) name;
//end interface.

//------- start body ---------------
static MyNativePluginAppController delegateObject; // --- a static object is defined to be called from "extern" method.

@implementation MyNativePluginAppController

//synthesize variables.
@synthesize myNativePlugin;

// overriding main unity entry point.

-(void) startUnity: (UIApplication) application { 
   [super startUnity: application]; //call the super.
   [self initNativePlugin]; //call method to initialize our plugin class.

   delegateObject = self; // --- we assign this instance to the static delegateObject.

-(void) initNativePlugin {
   myNativePlugin = [[myNativePlugin alloc] init]; //initialize our plugin class.

-(void) doCallNativePlugin:(NSString) name {
   [myNativePlugin doMyNativePluginStuff:name ]; //call plugin

extern "C" { // -- we define our external method to be in C.
   void CallNativePlugin( const char* name ){
   NSString* justName = [[NSString alloc] initWithUTF8String:name]; // -- convert from C style to Objective C style.

   [delegateObject doCallNativePlugin:justName ]; // -- call method to plugin class


//setting this as app controller.

This will conclude the

A small recap.

  1. We created our plugin class which will do our native stuff.
  2. We created our UnityAppController subclass, which has our custom initialization methods.
  3. We added a “delegateObject”, which is a static variable in the UnityAppController class of type MyNativePluginAppController.
    We need this to be static because the “extern” method cannot access variables defined inside the AppController subclass. This way, we ensure it is always accessible.
  4. We assigned the instance of the UnityAppController subclass to the delegateObject in startUnity.
  5. We added an “Extern” method which Unity3D can call and will trigger our plugin.

!! It is important to have our newly made UnityAppController subclass saved outside of our xCode project.
At compile time, Unity3D creates a new ( or overwrites the old ) project. By saving the file inside your xCode project Unity3D will remove / overwrite it.
We will add this later inside the Unity Project.

5. Compiling our native library.

Now that we have our project setup and coded correctly we are about to compile the project into a native static library ( .a file ).
For this to work correctly we have to connect our iOS device ( preferably a 64 bit ) to our computer.
Select the project in the project view and make sure you have the correct architectures selected.


For this plugin I am going to support the following device architectures:

  1. ARMv7
  2. ARM64

Other device architectures that can be supported are

  1. ARMv6
  2. ARMv7S

These are the architectures on which your plugin will run. Other architectures will fail loading the plugin as you have not supported them.

Now select the correct target and set the target device to the connected device.


With these steps setup correctly, press “RUN” or the Play button.

If all goes well, your static library has now been made.
You will get errors if this fails, but if not you’ll see your “red files” in project view become black.


Right click the .a file and select “Show in finder”, which will take you to the file location.

You have successfully compiled an iOS library which can be used in Unity3D projects for iOS devices.

6. Implementing the native plugin inside Unity3D.

Reproduce the following steps inside Unity3D:

  1. Open Unity3D and load your project.
  2. Create a “Plugins” folder with an “iOS” folder inside. Place the “Plugins” folder inside the “Assets” folder.
  3. Place the generated .a file inside the “iOS” folder together with the AppController subclass and plugin header ( and MyNativePlugin.h )

Your native plugin is now ready to go!
Let’s look at the C# code to call our native plugin.

//connect to the extern method in Objective-C
extern static public void CallNativePlugin( string filename);

//Call the method from Unity3D.
CallNativePlugin( "this is a string");

// Native plugin has been called.

And that’s it!
To test it, build your project for iOS and test it on your device.

Happy coding 😀