natbro / UnityPlugin

example of callbacks, recurring callbacks, buffer marshaling from native-code to Unity/C#
103 stars 9 forks source link

UnityPlugin

This is an example native-code plugin for Unity 4.x demonstrating how to perform various kinds of callbacks, recurring callbacks, and data buffer marshaling back into your C# scripts. I pulled these simple examples out of a project I'm working on because I didn't find the Unity documentation useful, nor was it easy to find concise or efficient tutorials. There is a lot of horrible, horrible and just plain wrong information about data-types, delegates, and C# marshaling out there. I had to piece a great deal of information together from many different sources, including:

I'll put some top-level information here, but read the comments in UnityPlugin.cs and UnityPlugin.m for the real details about how everything works together, how to keep yourself from crashing Unity by calling back on the wrong thread(s), how to do proper setup/teardown, how to manage delegate and callback lifecycles, and how to (try to) minimize copy-overhead if you are using these techniques to flow real-time data between your native code and Unity/C#.

The Unity Plugin

For Mac or iOS: an XCode UnityPlugin project which creates a 32-bit UnityPlugin.bundle. Note the comments about disabling ARC, (required for 32-bit on Mac, which is required for Unity 4.x) and in general this is a better "best-practices" template .h/.m and XCode project for building your own plugin.

For Windows: TBD (feel free to fork/contribute a pull-request - 99% of the UnityPlugin.m code is pure ANSI-C - it's just a matter of doing different debug logging and writing a different message-pump and recurring timer).

For Linux: TBD (again, feel free to fork/contribute)

Unity Example Project

The test Unity project UnityPluginTest is simply a default scene with a cube with the UnityPlugin.cs script component attached to it. When run results of the example are purely Console Debug.Log output.

Setup / Installation / Tips

10/15/14 10:41:04.901 AM Unity[20962]: UnityPlugin: initializer
10/15/14 10:41:04.910 AM Unity[20962]: UnityPlugin: reply_during_call
10/15/14 10:41:04.910 AM Unity[20962]: UnityPlugin: set_recurring_reply(6622,0x19bd10c8)
10/15/14 10:41:04.911 AM Unity[20962]: UnityPlugin: poll_data(6622,0xbfffc9c8,0xbfffc9cc)
10/15/14 10:41:04.911 AM Unity[20962]: UnityPlugin: set_recurring_reply(6622,0x19bd1188)
10/15/14 10:41:06.911 AM Unity[20962]: UnityPlugin: recurring invocation loop
10/15/14 10:41:06.911 AM Unity[20962]: UnityPlugin: block is <__NSMallocBlock__: 0x19c3ae50>
10/15/14 10:41:06.913 AM Unity[20962]: UnityPlugin: block is <__NSMallocBlock__: 0x19c25c80>
10/15/14 10:41:25.399 AM Unity[20962]: UnityPlugin: finalizer
testing callbacks on object:6630
one-time callback on Cube (UnityEngine.GameObject)
polled 862 bytes into C# as System.Byte[]
recurring on Cube (UnityEngine.GameObject) called at 1.940374
recurring data push on Cube (UnityEngine.GameObject) called at 1.940374
transferred 21 bytes into C# as System.Byte[]
recurring on Cube (UnityEngine.GameObject) called at 3.935837
recurring data push on Cube (UnityEngine.GameObject) called at 3.935837
transferred 491 bytes into C# as System.Byte[]
recurring on Cube (UnityEngine.GameObject) called at 5.952033
recurring data push on Cube (UnityEngine.GameObject) called at 5.952033
transferred 668 bytes into C# as System.Byte[]