Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C iOS plug-ins for Unity

I'm having an issue building the Unity3d project in Xcode (to test on a device) with a Objective C plug-in I've made.
Here are the files:

The TestPlugin.h file:

#import <Foundation/Foundation.h>

@interface TestPlugin : NSObject

+(int)getGoodNumber;
@end

The TestPlugin.m file:

#import "TestPlugin.h"

@implementation TestPlugin

+(int)getGoodNumber
{
    return 1111111;
}

@end

And finally the C# script in unity that's supposed to print out the value that getGoodNumber() returns:

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class PluginTest : MonoBehaviour
{
    [DllImport ("__Internal")]
    public static extern int getGoodNumber();

    void OnGUI()
    {
        string goodNum = getGoodNumber().ToString();
        GUILayout.Label (goodNum);
    }

}

As much as I can tell there shouldn't be any problem with the code. But even though I followed many different tutorials, when I try to compile I get an error in Xcode:

Undefined symbols for architecture armv7:
  "_getGoodNumber", referenced from:
      RegisterMonoModules() in RegisterMonoModules.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I tried a million different things and nothing seems to help. As much as I could read from other tutorials I do not need any special settings for Xcode and I can leave them same as it was for the Unity project without the plug-in.

I would also like to clarify a few things:

  • The plugin files are located in /Plugins/iOS/ folder in Unity3d
  • The build target was iPad Air 2 with the latest iOS, so no problem should arise there. Also using the newest Xcode on the newest OS X version.
  • I have the newest available version of Unity3d, and if that matters - I do have the Pro version of Unity3d.
  • The project works if the plugin is removed, so it's not a problem between Unity3d and Xcode.
  • I do not think I need to use extern "C" wrapper in Objective-C code as it's a ".m" file, not ".mm", so there shouldn't be a problem of name-mangling.
  • The plug-in was created in Xcode through the "Cocoa Touch Static Library" template. I was able to successfully build the Xcode project by itself before importing it to Unity3d.

If someone encountered such a problem as solved it, I would love to hear the solution.

like image 862
Creative Magic Avatar asked Jan 07 '23 07:01

Creative Magic


1 Answers

You've written an "objective-c" class and method, but that can not be exposed to Unity. You need to create a "c" method (which could then call an objective-c method if needed).

Eg:

plugin.m:

long getGoodNumber() {
  return 111;
}

Here is a fuller example that demonstrates out params to get a gyro.

Let's make a motion manager to get gyro (faked out for now). This would be standard objective-c:

MyMotionManager.h

@interface MyMotionManager : NSObject { }

+(MyMotionManager*) sharedManager;
-(void) getGyroXYZ:(float[])xyz;

@end

MyMotionManager.m:

@implementation MyMotionManager

+ (MyMotionManager*)sharedManager
{
    static MyMotionManager *sharedManager = nil;
    if( !sharedManager )
        sharedManager = [[MyMotionManager alloc] init];
    return sharedManager;
}

- (void) getGyroXYZ:(float[])xyz
{
    // fake
    xyz[0] = 0.5f;
    xyz[1] = 0.5f;
    xyz[2] = 0.5f;
}

@end

Now lets expose it via a C external reference (no need for extern as it's in a .m (not a .mm):

MyMotionManagerExterns.m:

#import "MyMotionManager.h"

void GetGyroXYZ(float xyz[])
{
    [[MyMotionManager sharedManager] getGyroXYZ:xyz];
}

Finally, in Unity C# lets call it:

MotionPlugin.cs:

using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;

public class MotionPlugin 
{
    [DllImport("__Internal")]
    private static extern void GetGyroXYZ(float[] xyz);

    public static Vector3 GetGyro()
    {
        float [] xyz = {0, 0, 0};
            GetGyroXYZ(xyz);
            return new Vector3(xyz[0], xyz[1], xyz[2]);
    }
}
like image 110
peterept Avatar answered Jan 14 '23 18:01

peterept