Construyendo Plugins para Plataformas de Escritorio
AssetBundles

Interfaz de Plugin Nativo de Bajo Nivel

Adicionalmente a la interfaz básica de script, los Native Code Plugins en Unity pueden recibir callbacks cuando ciertos eventos ocurre. Esto en su mayoría es utilizado para implementar un renderizado de bajo nivel en su plugin y le permite funcionar con el renderizado multi-hilo (multithread) de Unity.

Headers defining interfaces exposed by Unity are provided with the editor.

Interface Registry

A plugin should export UnityPluginLoad and UnityPluginUnload to handle main Unity events. See IUnityInterface.h for the correct signatures. IUnityInterfaces is provided to the plugin to access further Unity APIs.

    #include "IUnityInterface.h"
    #include "IUnityGraphics.h"
    // Unity plugin load event
    extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
        UnityPluginLoad(IUnityInterfaces* unityInterfaces)
    {
        IUnityGraphics* graphics = unityInterfaces->Get<IUnityGraphics>();
    }

Acceso al Dispositivo de Gráficas

A plugin can access generic graphics device functionality by getting the IUnityGraphics interface. In earlier versions of Unity a UnitySetGraphicsDevice function had to be exported in order to receive notification about events on the graphics device. Starting with Unity 5.2 the new IUnityGraphics interface (found in IUnityGraphics.h) provides a way to register a callback.

    #include "IUnityInterface.h"
    #include "IUnityGraphics.h"
    
    static IUnityInterfaces* s_UnityInterfaces = NULL;
    static IUnityGraphics* s_Graphics = NULL;
    static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
    
    // Unity plugin load event
    extern "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 event
    extern "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
                break;
            }
            case kUnityGfxDeviceEventShutdown:
            {
                s_RendererType = kUnityGfxRendererNull;
                //TODO: user shutdown code
                break;
            }
            case kUnityGfxDeviceEventBeforeReset:
            {
                //TODO: user Direct3D 9 code
                break;
            }
            case kUnityGfxDeviceEventAfterReset:
            {
                //TODO: user Direct3D 9 code
                break;
            }
        };
    }

Callbacks del Plugin en el hilo renderizando

El renderizado en Unity puede ser multi-hilo si la plataforma y el número de CPUs disponibles lo permiten. Cuando el renderizado multi-hilo es usado, los comandos del API de renderizado sucede en un hilo que es completamente diferente del que está ejecutando los scripts de MonoBehaviour. En consecuencia, no es siempre posible para su plugin que empiece hacer algo de renderización inmediatamente, ya que podría interferir con lo que el hilo de renderizado esté haciendo en ese tiempo.

Con el fin de hacer cualquier renderizado desde el plugin, usted debería llamar GL.IssuePluginEvent desde su script, lo cual va a causar que su plugin sea llamado del hilo que renderiza. Por ejemplo, si usted llama GL.IssuePluginEvent de la función de la cámara OnPostRender, usted puede obtener un callback del plugin inmediatamente después de que la cámara ha finalizado de renderizar.

Signature for the UnityRenderingEvent callback is provided in IUnityGraphics.h. Native plugin code example:

    // Plugin function to handle a specific rendering event
    static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
    {
        //TODO: user rendering code
    }
    
    // Freely defined function to pass a callback to plugin-specific scripts
    extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
        GetRenderEventFunc()
    {
        return OnRenderEvent;
    }

Managed plugin code example:

    #if UNITY_IPHONE && !UNITY_EDITOR
    [DllImport ("__Internal")]
    #else
    [DllImport("RenderingPlugin")]
    #endif
    private static extern IntPtr GetRenderEventFunc();
    
    // Queue a specific callback to be called on the render thread
    GL.IssuePluginEvent(GetRenderEventFunc(), 1);

Tales callbacks pueden ser también agregados a CommandBuffers vía CommandBuffer.IssuePluginEvent.

Ejemplo

Un ejemplo de un plugin de renderizado de bajo nivel puede ser descargado aquí. Este muestra dos cosas:

  • Renderiza un triángulo girando desde código C++ después de que todo el renderizado regular se ha hecho.
  • Llena una textura de procedimiento desde código C++, utilizando Texture.GetNativeTexturePtr para acceder a ello.

El proyecto funciona con:

  • Windows (Visual Studio 2008) y Mac OS X (Xcode 3.2) y utiliza Direct3D 9, Direct3D 11 o OpenGL dependiendo en la plataforma. Código de la pieza de Direct3D 9 también demuestra cómo manejar dispositivos “perdidos”.
  • Windows Store Apps (ver RenderingPlugin\WSAVisualStudio2012 para más información)
Construyendo Plugins para Plataformas de Escritorio
AssetBundles