Author: stefansigl

Writing native MacOSX plugins using Objective C for Unity

Im writing this caus in the attempt of creating a native plugin using objective c i had some fallbacks, minor ones but still. I hadn’t found a clear statement about my problem.

My Problem was that i got the EntryPointNotFoundException when trying to call my native function from within unity or mono for that matter and i could not tell why.

What I was missing was that i needed to write a c wrapper for my objective c code inside the plugin. And then calling the c wrapper function using a c# wrapper inside unity ( last part is same with c/c++ plugins)

So in the following i will describe THE WAY or at least my approach to do this.

I’m using a mac with El Capitan (10.11.5) and Xcode version 7.3.1 as well as Unity 5.3.5p4 (i think any Unity Xcode or OS X version will work but now you know my setup if you run into problems)

The Xcode Part:

At first you have to create a new XCode project to create the bundle.

In there you have to create 3 files:

  • Wrapper.m
  • Plugin.h
  • Plugin.m

The Wrapper.m contains the wrap code for your Objective c plugin:

</pre>
#import <Foundation/Foundation.h>

#import "Plugin.h"

#define GetStringParam( _x_ ) ( _x_ != NULL ) ? [NSString stringWithUTF8String:_x_] : [NSString stringWithUTF8String:""]

extern void Message(char* msg)

{

Plugin* helper = [[Plugin alloc]init];

[helper log:GetStringParam(msg)];

&nbsp;

}

 

Plugin.h

</pre>
#ifndef Plugin_h

#define Plugin_h

#import <Foundation/Foundation.h>

@interface Plugin: NSObject

{

}

- (void) log: (NSString *) message;

@end

#endif

Plugin.m

</pre>
#import <Foundation/Foundation.h>

#import "Plugin.h"

#import <Cocoa/Cocoa.h>

@implementation Plugin : NSObject

NSOpenPanel *panel;

- (void) log: (NSString *) message

{

NSLog(@"Passed message = %@", message);

}

@end
<pre>

With that code set up you can compile your code in Xcode to generate the .bundle in my case Plugin.bundle

Now the Unity Part:
In Unity you have to put your bundle into the Plugins folder if you dont have one create it. (See unity docu about special folder names if you want to know more).

Screen Shot 2016-08-12 at 14.46.22

When the bundle is imported you can set some Properties in the inspector upon clicking on it. You should mark the appropriate Platformsettings (in this case MacOSX x86 and MacOSX x_86_64

Screen Shot 2016-08-12 at 14.46.34

With thats done you need to write the c# wrapper for your native plugin.

Create a c# file, i name it PluginTest.cs

PluginTest.cs

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

public class TestPlugin : MonoBehaviour
{
    
    [DllImport(Plugin)]
    extern static private void Message(string message);

    public void Msg ()
    {
        Message (Hello World);
    }
        
    void OnGUI()
    {
        if (GUILayout.Button(Write Message))
        {
            Msg ();
        }
    }
}

We need to use the System.Runtime.InteropServices; in order to include the Plugin. Also we need to DllImport it using the [DllImport(“PLUGINNAME”)] statement (in my case the bundle is called Plugin so i write [DllImport(“Plugin”)] and then what Method from the Dll is marked as extern below.
With that done we can call this Method like a normal c# method.

In this case i added an OnGUI Button to test it.

Attach the Script to a Gameobject in your scene.


You’ll notice there is nothing coming up in the Console Log, this is okay! To achieve this we would need a response from the plugin and Debug.Log it ourselves. In this case we can check it by looking at the Editor Log.
Screen Shot 2016-08-12 at 15.02.07
Here’s our native log:
Screen Shot 2016-08-12 at 15.03.00.png
Passed message = Hello World is what our plugin is putting out.

So i hope i could help and now it’s up to you to write whatever awesome native plugin you can imagine.

 

[uGUI]PanelManager v1.4

The new feature in this Version is First Selected.

Bildschirmfoto 2015-12-29 um 12.44.13.png

 

You now can set the First Selected GameObject on each managed panel. This directly accesses Unity’s eventsystem and sets the GameObject in the appropriate slot.

This helps especially when creating controller based ui control schemes.

 

 

And of course thanks to all who are submitting bugs.

  • Fixed a bug there you could only add one script call in a slot like “Call before show” cause the slots did not expand properly.

 

Version is currently in unity’s review process and should be out during the next days.

Ran out of Trampolines

If Xcode tells you that you ran out of trampolines and your app crashes, don’t worry your application still can jump on your IOS device 😉 If you heavily use recursive Generics (type 1) or like in my case interfaces (type 2) just set the AOT settings higher!

I had a great laugh when i read for the first time that my Application ran out of trampolines 🙂 

Type 0 (default 1024)

-aot “ntrampolines=2048”

Type 1 (default 1024)

-aot “nrgctx-trampolines=2048”

Type 2 (default 128)

-aot “nimt-trampolines=512”

 

Just go to your Unity3D PlayerSettings -> Other -> AOT Compilation Options and paste the line from above there:

Ran out of Trampolines type 2

AOT Compilation Options in PlayerSettings under Other Settings

 

Source: http://developer.xamarin.com/guides/ios/troubleshooting/troubleshooting/

 

have fun jumping on your new trampolines 🙂

[uGUI]PanelManager 1.2 Released

Version 1.2 is now live in the AssetStore

Release Notes:

  • Fixed bug were Methods (before enter state and before leave state) where not called when transition duration was zero
  • Fixed bug in PanelSwitcher component where hiding a hidden panel resulted in showing it
  • Fixed Null reference bug in PanelSwitcher component
  • Added: You can now set MainPanels to show instant on Start or SceneSwitch
  • Added: You can now have multiple mainPanels
  • Changed Calling Methods on changing state from to UnityEvents (previously Methods where called with „SendMessage“)
  •  Change: exposed
    • public static uGUIManagedPanel FindPanel(string name)
    • you can now get the instance or the GameObject of any panel by calling
    • uGUIManager.FindPanel(“PanelName”).CachedGameObject