1 / 6

Bridging the Gap – Plugin for Unity and iOS

App42 Unity3d Plugin for iOS allows you to implement iOS native code and with this sample you can add objective c side codes without making changes directly to the Unity generated Xcode project.

shephertz
Télécharger la présentation

Bridging the Gap – Plugin for Unity and iOS

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Bridging the Gap – Plugin for Unity and iOS There is always a need of finding out a way of communication from unity to XCode or XCode to unity due to the absence of a direct way. For the first time when I faced this problem, had to spend almost 3-4 days of my app’s development cycle on finding the right way to make this bridge. Through this blog post, I am going to share the method so as to help out any other developer like me. Creating a bridge over unity and iOS requires coding at both ends. So, let’s discuss XCode side first. According to Unity documentation, “Unity iOS supports automated plugin integration in a limited way. All files with extensions .a,.m,.mm,.c,.cpp located in the Assets/Plugins/iOS folder will be merged into the generated Xcode project automatically. However, merging is done by symlinking files from Assets/Plugins/iOS to the final destination, which might affect some workflows. The.h files are not included in the Xcode project tree, but they appear on the destination file system, thus allowing compilation of .m/.mm/.c/.cpp files”. So, we will create UnityIOSBridge.m and will place this class to the path “Assets/Plugins/iOS”.Unity needs the plugins to be c named so it is a good practice to wrap up the methods which need to be called from unity, inside extern “C”. But there is no hard and fast rule, you can create .m class and write your c-named methods just outside the implementation part and you can call them from unity. The only constraint is that you can not call these methods if you are building your App on simulator as unity iOS plugins only work on device. Also Read: Steps to Integrate Push Notification with Unity3D on iOS

  2. Let’s do some coding e.g. in UnityIOSBridge.m class just write a method that can receive a string and convert it to NSString, now UnityIOSBridge.m class should look like as follows: #import"UnityIOSBridge.h" void messageFromUnity(char *message) { NSString *messageFromUnity = [NSString stringWithUTF8String:message]; NSLog(@"%@",messageFromUnity); } @implementation UnityIOSBridge @end To call the above written method from Unity, we have to write a Unity script, so let’s create a file UnityIOSBridge.cs. using UnityEngine; using System.Collections; using System; //This is needed to import iOS functions using System.Runtime.InteropServices; public class UnityIOSBridge : MonoBehaviour { /* * Provide function decalaration of the functions defined in iOS * and need to be called here. */ [System.Runtime.InteropServices.DllImport("__Internal")] extern static public void messageFromUnity(string message); //Sends message to iOS static void SendMessageToIOS() {

  3. messageFromUnity("Hello iOS!"); } } And it’s really as simple as it looks in the above code. Now to call a method written in Unity script from iOS code, we can call UnitySendMessage(“UnityObjectName”, “UnityObject’sMethodName”, “Your message”). In response, Unity will look for the UnityObject and then call that UnityObject’sMethod to provide the message you passed. Now the UnityIOSBridge.m class should look like: #import"UnityIOSBridge.h" void messageFromUnity(char *message) { NSString *messageFromUnity = [NSString stringWithUTF8String:message]; NSLog(@"%@",messageFromUnity); } @implementation UnityIOSBridge -(void)sendMessageToUnity { UnitySendMessage(listenerObject, "messageFromIOS", "Hello Unity!"); } @end and the Unity script UnityIOSBridge.cs should look like: using UnityEngine; using System.Collections; using System; //This is needed to import iOS functions using System.Runtime.InteropServices; public class UnityIOSBridge : MonoBehaviour { /* * Provide function decalaration of the functions defined in iOS * and need to be called here. */

  4. [System.Runtime.InteropServices.DllImport("__Internal")] extern static public void messageFromUnity(string message); //Sends message to iOS static void SendMessageToIOS() { messageFromUnity("Hello iOS!"); } //Provides messages sent from iOS static void messageFromIOS(string message) { Debug.Log(message); } } Well this was a very simple requirement but what if we want to do something more e.g. our plugin should be able to notify Unity about the UIApplication delegate calls.There is no need to be worried as we are going to implement that also but to do that we have to do some work around.Objective-C is a runtime oriented language, which means that when it’s possible it defers decisions about what will actually be executed from compile & link time to when it’s actually executing on the runtime. Quick Tip: Download the readymade Push Notification Widget for Unity3D here. This gives you a lot of flexibility in that, you can redirect messages to appropriate objects as you need to or you can even intentionally swap method implementations etc. This requires the use of a runtime which can introspect objects to see what they do & don’t respond to and dispatch methods appropriately. So, we will take a simple example of “application: didFinishLaunchingWithOptions:” delegate method UIApplicationDelagate. We will be creating a category class of UIApplication and will implement load method. In load method, we will exchange the setDelagete method implementation of UIApplication with the method setApp42Delegate method of our class as follows: +(void)load {

  5. method_exchangeImplementations(class_getInstanceMethod(self, @selector(setDelegate:)), class_getInstanceMethod(self, @selector(setApp42Delegate:))); } -(void) setApp42Delegate:(id)delegate { static Class delegateClass = nil; if(delegateClass == [delegate class]) { return; } delegateClass = [delegate class]; exchangeMethodImplementations(delegateClass, @selector(application:didFinishLaunchingWithOptions:),@selector(application:app42d idFinishLaunchingWithOptions:), (IMP) app42RunTimeDidFinishLaunching, "v@:::"); [self setApp42Delegate:delegate]; } staticvoid exchangeMethodImplementations(Class class, SEL oldMethod, SEL newMethod, IMP impl, constchar * signature) { Method method = nil; //Check whether method exists in the class method = class_getInstanceMethod(class, oldMethod); if (method) { //if method exists add a new method class_addMethod(class, newMethod, impl, signature); //and then exchange with original method implementation method_exchangeImplementations(class_getInstanceMethod(class, oldMethod), class_getInstanceMethod(class, newMethod)); } else { //if method does not exist, simply add as orignal method class_addMethod(class, oldMethod, impl, signature); } } BOOL app42RunTimeDidFinishLaunching(id self, SEL _cmd, id application, id launchOptions) { BOOL result = YES; if ([self respondsToSelector:@selector(application:app42didFinishLaunchingWithOptions:)]) { result = (BOOL) [self application:application app42didFinishLaunchingWithOptions:launchOptions]; }

  6. else { [self applicationDidFinishLaunching:application]; result = YES; } [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; return result; } Let’s walk through the above code snippets, the method “setApp42Delegate” calls our “exchangeMethodImplementations” that adds the “app42RunTimeDidFinishLaunching” to UIApllication class and exchanges the implementations of “app42RunTimeDidFinishLaunching” with “application: didFinishLaunchingWithOptions:” if it exists.This way we can have the access of all the UIApplicationDelagate methods such “application:didRegisterForRemoteNotificationsWithDeviceToken:” etc, without making changes directly to the Unity generated Xcode project.You can download the source code of our Unity plugin for iOS push notifications from Git Repo. Get started with Unity3D backend with App42 here. If you have any questions or need any further assistance, please feel free to write us at support@shephertz.com as “applicationDidEnterBackground:”,

More Related