Low-level Native Plugin Interface
In addition to the basic script interface, Native Code Plugins in Unity can receive callbacks when certain events happen. This is mostly used to implement low-level rendering in your plugin and enable it to work with Unity's multithreaded rendering.
Access to the Graphics Device
A plugin can receive notification about events on the graphics device by exporting a UnitySetGraphicsDevice
function. This will be called when the graphics device is created, before it is destroyed, and also before and after the device is "reset" (this only happens with Direct3D 9). The function has parameters which will receive the device pointer, device type and the kind of event that is taking place.
// If exported by a plugin, this function will be called when graphics device is created, destroyed, // and before and after it is reset (ie, resolution changed). extern "C" void EXPORT_API UnitySetGraphicsDevice (void* device, int deviceType, int eventType);
Possible values for deviceType:
enum GfxDeviceRenderer { kGfxRendererOpenGL = 0, // OpenGL kGfxRendererD3D9 = 1, // Direct3D 9 kGfxRendererD3D11 = 2, // Direct3D 11 kGfxRendererGCM = 3, // Sony PlayStation 3 GCM kGfxRendererNull = 4, // "null" device (used in batch mode) kGfxRendererHollywood = 5, // Nintendo Wii kGfxRendererXenon = 6, // Xbox 360 kGfxRendererOpenGLES = 7, // OpenGL ES 1.1 kGfxRendererOpenGLES20Mobile = 8, // OpenGL ES 2.0 mobile variant kGfxRendererMolehill = 9, // Flash 11 Stage3D kGfxRendererOpenGLES20Desktop = 10, // OpenGL ES 2.0 desktop variant (i.e. NaCl) };
Possible values for eventType:
enum GfxDeviceEventType { kGfxDeviceEventInitialize = 0, kGfxDeviceEventShutdown = 1, kGfxDeviceEventBeforeReset = 2, kGfxDeviceEventAfterReset = 3, };
Plugin Callbacks on the Rendering Thread
Rendering in Unity can be multithreaded if the platform and number of available CPUs will allow for it. When multithreaded rendering is used, the rendering API commands happen on a thread which is completely separate from the one that runs MonoBehaviour scripts. Consequently, it is not always possible for your plugin to start doing some rendering immediately, since might interfere with whatever the render thread is doing at the time.
In order to do any rendering from the plugin, you should call GL.IssuePluginEvent from your script, which will cause your plugin to be called from the render thread. For example, if you call GL.IssuePluginEvent from the camera's OnPostRender function, you get a plugin callback immediately after the camera has finished rendering.
// If exported by a plugin, this function will be called for GL.IssuePluginEvent script calls. // The function will be called on a rendering thread; note that when multithreaded rendering is used, // the render thread WILL BE DIFFERENT from the main thread, on which all scripts & other game logic are executed! // You have responsibility for ensuring any necessary synchronization with other plugin script calls takes place. extern "C" void EXPORT_API UnityRenderEvent (int eventID);
Example
An example of a low-level rendering plugin can be downloaded here. This simply draws a rotating triangle from C++ code after all regular rendering is done. The project works with Windows (Visual Studio 2008) and Mac OS X (Xcode 3.2) and uses Direct3D 9 on Windows and OpenGL on both platforms.The Direct3D 9 project also demonstrates how to handle "lost" devices.
Page last updated: 2011-11-02