Version: 2017.4
Optimizing Physics Performance
Preparing your application for In-App Purchases (IAP)

Building plug-ins for iOS

This page describes how to build native code plug-ins for the iOS platform.

Building an application with a native plug-in for iOS

To build an application with a native plug-in for iOS, follow these steps:

  1. For each native function you want to call, define an extern method in the C# file as follows:

    [DllImport ("__Internal")] 
        
    private static extern float FooPluginFunction();
    
  2. Add your native code source files to the Unity Project.

  3. Customize the plug-in’s settings in the Plugin Inspector window. For example, if your native code is iOS-specific, make sure the plug-in is only enabled for iOS.

Note: If you are using C++ (.cpp) or Objective-C++ (.mm) to implement the plug-in, you must declare functions with C linkage to avoid issues with name mangling:

extern "C" {
  float FooPluginFunction();
}

Plug-ins written in C or Objective-C don’t need this, because these languages don’t use name mangling.

Using your plug-in from C

Your app can only call iOS native plug-ins when it’s deployed on an actual device, so you should wrap all native code methods with an additional C# code layer. This code should either use UNITY_IOS && !UNITY_EDITOR conditional compilation, or check Application.platform and only calll native methods when the app is running on a device. A simple way to implement this is:

void MyMethod()
{
#if UNITY_IOS && !UNITY_EDITOR
    CallNativeMethodImplementation();
#else
    CallEditorMethodImplementation();
#endif
}

For a more detailed implementation, download the Bonjour Browser Sample below.

Calling C# back from native code

Unity iOS supports limited native-to-managed callback functionality. You can do this in one of two ways: * Using UnitySendMessage * Via delegates

Using UnitySendMessage

This option is simpler, but has some limitations. It looks like this:

UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");

There are three parameters: * The name of the target GameObject * The script method to call on that object * The message string to pass to the called method

Using UnitySendMessage has the following limitations:

  1. From native code, you can only call script methods that correspond to the following signature: void MethodName(string message);.
  2. Calls to UnitySendMessage are asynchronous and have a delay of one frame.
  3. If two or more GameObjects have the same name, this can cause conflicts wHEN YOU USE UnitySendMessage.

Using delegates

This is the more complex option. When you use delegates, the method on the C# side must be static and be marked with the MonoPInvokeCallback attribute. You must pass the method as a delegate to the extern method which is implemented in native code as a function that takes a pointer to function with the corresponding signature. The function pointer in the native code then leads back to the C# static method.

The C# code for this method looks like this:

delegate void MyFuncType();

[AOT.MonoPInvokeCallback(typeof(MyFuncType))]

static void MyFunction() { }

static extern void RegisterCallback(MyFuncType func);

The C code that accepts the callback then looks like this:

typedef void (*MyFuncType)();

void RegisterCallback(MyFuncType func) {}

Automated plug-in integration

Unity supports automated plug-in integration and copies all files with the following extensions to the generated Xcode project if you enable them for iOS in the Plugin Inspector window: .a, .m , .mm, .c, .cpp, .h. If any files with these extensions are located n the Assets/Plugins/iOS folder, Unity only enables them for the iOS platform.

Note: After the files are copied to the generated Xcode project, they’re no longer linked to their counterparts in your Unity Project. If you change these files in Xcode, you must copy them back into your Unity Project. Otherwise, Unity will overwrite them the next time you build your Project.

This Inspector window shows that the plug-in has been enabled for iOS.
This Inspector window shows that the plug-in has been enabled for iOS.

Tips for iOS:

  1. Managed-to-unmanaged calls are quite processor-intensive on iOS. Try to avoid calling multiple native methods per frame.

  2. Wrap your native methods with an additional C# layer that calls native code on the device and returns dummy values in the Editor.

  3. String values returned from a native method should be UTF–8 encoded and allocated on the heap. Mono marshalling calls free for strings like this.

Bonjour Browser Sample

You can download a simple example of how to use a native code plug-in here: Bonjour Browser Sample.

This example demonstrates how you can invoke bjective-C code from a Unity iOS application. This application implements a simple Bonjour client and consists of:

  • A Unity iOS Project where Plugins\Bonjour.cs is the C# interface to the native code, and BonjourTest.cs is the script that implements the application logic
  • Native code (located in Assets/Plugins/iOS) that should be added to the built Xcode project as described in the Automated plug-in integration section above
Optimizing Physics Performance
Preparing your application for In-App Purchases (IAP)