Introduction to native plug-in API
Locate the native plug-in API files and import them into your native plug-in.
Read time 4 minutesLast updated 17 days ago
Native Plug-ins in Unity can receive callbacks when certain events happen. You can use this to implement low-level rendering in your plug-in so it can work with Unity’s multithreaded rendering.
Interface Registry
To handle main Unity events, a plug-in must export and functions. IUnityInterfaces enables the plug-in to access these functions, which you can find in in the plug-in API:
UnityPluginLoadUnityPluginUnloadIUnityInterface.h#include "IUnityInterface.h"#include "IUnityGraphics.h"// Unity plugin load eventextern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces){ IUnityGraphics* graphics = unityInterfaces->Get<IUnityGraphics>();}
Access to the graphics device
Use the interface, which you can find in , to give a plug-in access to generic graphics device functionality. This script demonstrates how you can use the interface to register a callback:
IUnityGraphicsIUnityGraphics.hIUnityGraphics#include "IUnityInterface.h"#include "IUnityGraphics.h" static IUnityInterfaces* s_UnityInterfaces = NULL;static IUnityGraphics* s_Graphics = NULL;static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull; // Unity plugin load eventextern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces){ s_UnityInterfaces = unityInterfaces; s_Graphics = unityInterfaces->Get<IUnityGraphics>(); s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); // Run OnGraphicsDeviceEvent(initialize) manually on plugin load // to not miss the event in case the graphics device is already initialized OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);} // Unity plugin unload eventextern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload(){ s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);} static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType){ switch (eventType) { case kUnityGfxDeviceEventInitialize: { s_RendererType = s_Graphics->GetRenderer(); //TODO: user initialization code on graphics device initialization. For example, D3D11 resource creation. break; } case kUnityGfxDeviceEventShutdown: { s_RendererType = kUnityGfxRendererNull; //TODO: user graphics API code to call on graphics device shutdown. break; } case kUnityGfxDeviceEventBeforeReset: { //TODO: user graphics API code to call before graphics device reset. break; } case kUnityGfxDeviceEventAfterReset: { //TODO: user graphics API code to call after graphics device reset. break; } };}
Plug-in callbacks on the rendering thread
You can use multithreading to render in Unity, if the platform and number of available CPUs allows for it.
To render from the plug-in, call GL.IssuePluginEvent from your managed plug-in script. This causes Unity’s rendering pipeline to call the native function from the render thread, as demonstrated in the code example below. For example, if you call GL.IssuePluginEvent from the Camera’s OnPostRender function, the function will call a plug-in callback immediately after the camera has finished rendering.
Native plugin code:
// Plugin function to handle a specific rendering eventstatic void UNITY_INTERFACE_API OnRenderEvent(int eventID){ // User rendering code} // Freely defined function to pass a callback to plugin-specific scriptsextern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc(){ return OnRenderEvent;}
Managed plug-in code:
#if UNITY_IPHONE && !UNITY_EDITOR[DllImport ("__Internal")]#else[DllImport("RenderingPlugin")]#endifprivate static extern IntPtr GetRenderEventFunc(); // Queue a specific callback to be called on the render threadGL.IssuePluginEvent(GetRenderEventFunc(), 1);
The signature for the callback is provided in IUnityGraphics.h in the Native Rendering Plugin sample.
UnityRenderingEventPlug-in using the OpenGL graphics API
There are two kinds of OpenGL objects:
- Objects shared across OpenGL contexts, such as texture, buffer, renderbuffer, samplers, query, shader, and program objects.
- Per-OpenGL context objects, such as vertex array, framebuffer, program pipeline, transform feedback, and sync objects.
Unity uses multiple OpenGL contexts. When initializing and closing the Editor and the Player, Unity relies on a master context, but when rendering it uses dedicated contexts. That is, you can’t create per-context objects during and events.
kUnityGfxDeviceEventInitializekUnityGfxDeviceEventShutdownPlug-in using the Vulkan graphics API
When developing a native graphics plug-in that uses the Vulkan graphics API, you can enable debugging through the validation layers. To enable the validation layers, ensure the following to prevent crashes during plug-in execution:
- Add a validation layer plug-in in the same directory as the native graphics plug-in.
- Configure identical Load on Startup settings for both the native and the Vulkan validation layer plug-ins in the plug-in Inspector window.