Now that we have the plugin working on the device, we want to get it working in the Editor too. This step is of course optional, but it’s what makes great plugins really stand out. Vuforia is a great example of this. The ability to work and test in the Editor saves tons of time, and will be appreciated by your users.
This is a frustrating process, for a few reasons. The Unity Editor (as of Unity 4.2, hopefully this is changing soon!) is still 32-bit. This means that plugins for it must also be 32-bit. However, a lot of nice Objective-C features (like ARC, and automatic property synthesis) require the newer runtime, which is 64-bit. This means that in order for your plugin to work in the Editor you’ll need to use Objective-C 1.0, and your code will get a lot more messy as a result.
Let’s start by creating a new target for our native code. In Xcode, go to your project view, and click “Add Target..” You want an OS X Bundle, with Core Foundation:
You'll need to configure a few settings, specifically to build for only 32-bit:
If you don’t build for strictly 32-bit, the Editor won’t be able to load your DLL, and will probably give you a DLL not found exception.
Next, you’ll need to update some of your code to add @synthesize calls, etc:
When you can build, open up your Products folder in Finder, and find your bundle:
Copy that file into the Plugins/ directory of your Unity project. Be warned, the Unity Editor only reloads DLL’s on launch, not when they change. So, if you update your code and rebuild the bundle, Unity won’t see the changes until you restart the Editor!
Now we just need to tell our Unity code to use that bundle when it’s in the editor:
Then update all of your external calls and platform checks:
Note that we’ve changed the name of the DLL import. On non-iOS platforms, plugins can be loaded by name (without the extension). Again, if you get DLL not found exceptions, double check that this name is spelled correctly! Then double check you built your bundle for 32-bit!
One drawback of working in the Editor is that we can’t see log output from our plugin. In fact, we have no mechanism for the plugin to communicate back to Unity. On iOS we can use UnitySendMessage() to send things back to Unity, but this function doesn’t exist for the Editor (or desktop platforms). Instead, we’ll write a callback function and pass back a string.
You’ll probably note that MonoPInvokeCallback isn’t defined. You’ll need to define it yourself.
This allows the Editor to map your delegate methods into a native method.
On the native side we need to define a type for the callback, and set up a property to connect it to.
Whenever you call the unityLog: method, you should now get a Debug.Log in the Editor. This whole thing isn’t entirely necessary, but it’s helpful for debugging, or if you need to get values back from your plugin.
This particular plugin would work fine without the callback functions, but others would not. At this point, it should be basically up and running in the Editor!
This isn’t exactly a robust plugin, but by now it’s basically done. Pat yourself on the back, if you followed all the way through and got it up and running! As you can see, the initial setup is the hardest part. But if you’re comfortable in Objective-C (or even if you’re not), once you get past that initial hurdle writing native plugins is pretty easy.
The full source is available on our GitHub: https://github.com/addispatch/VideoMesh