Search Unity

Calling an Objective C function in an iPad app, from Unity

Discussion in 'iOS and tvOS' started by World View, May 23, 2012.

  1. World View

    World View

    Joined:
    Jan 27, 2011
    Posts:
    4
    We are embedding a Unity application within an Xcode project for an iPad app.

    We are using Unity 3.5 Pro.

    We want to call a method in the Objective C code of the app, from a Unity script, when a button is touched in the Unity GUI.

    Please can someone post a Unity script here showing exactly how to make this call. We've tried various options after searching on this topic, but none of them has worked. We are looking for a definitive answer.

    Thanks.
     
  2. Glockenbeat

    Glockenbeat

    Joined:
    Apr 24, 2012
    Posts:
    669
    I had quite some hassle with that last week too, but in the end it turns out that this is not as difficult as it seems. Basically this needs a couple of steps. I'll use my implementation of Appirater as an example:

    1. Your Objective-C functions. I found it to be the best to include my .h and .mm files in /Plugins/iOS.
    All functions which need to be called from inside Unity need to be wrapped in "extern "C"" statements:

    Code (csharp):
    1.  
    2. extern "C" {
    3.     void _userDidSignificantEvent(bool canPromptForRating, const char* title, const char* text, const char* rateNow, const char* rateLater, const char* dontRate) {
    4.        
    5.         // doing stuff
    6.        
    7.     }
    8. }
    9.  
    Basically I am just passing all my translations to the Appirater functions as I decided earlier to not maintain translations in XCode directly. I know, this may not be the best code, and it was my first approach to this topic, but it works fine.
    NOTE: using const char* was no accident! You'll need those to actually hand over strings from Unity to the native code.

    The next step will "link" Unity to the native code and provide functions which you can call from within Unity. This serves as some kind of wrapper:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class iOSAppirater {
    6.    
    7.     [DllImport ("__Internal")]
    8.     private static extern void _userDidSignificantEvent (bool canPromptForRating, string title, string text, string rateNow, string rateLater, string dontRate);
    9.    
    10.     public static void SignificantEvent(bool canPromptForRating, string title, string text, string rateNow, string rateLater, string dontRate) {
    11.         if (Application.platform == RuntimePlatform.IPhonePlayer) {
    12.             _userDidSignificantEvent(canPromptForRating, title, text, rateNow, rateLater, dontRate);
    13.         }
    14.     }
    15. }
    16.  
    Now the last step was to create methods to actually use these functions in the game, pretty easy, just instanciate the class as needed.

    Code (csharp):
    1.  
    2. var rater : iOSAppirater = new iOSAppirater(); 
    3.  
    I found quite some other threads concerning this topic, yet only little information on how to actually implement native code. Once you made it at least once all the docs are suddenly clear, sure, but it's a long road until that point. So I hope this helps.
     
  3. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    purchase one of Prime31's plugins, etcetera is a good example, and then look at the way he did it. I've used the pattern Prime31 used for this in all my projects, I think the way he put it together is ideal.

    basically the jist of it is you make a standard c file called UnityBinding.m and then put all your functions that unity tries to call into that, and then from that function have it call the objective c and c++ functions.
     
  4. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    388
    Im struggling with handing over the C strings to NSStrings, to be able to pass them in Objective C messages. Unfortunately, the samples above do not explain how this is being done. My naive way only resulted in a BAD_ACCESS crash :-/