デスクトップ向けのプラグインをビルド
アセットバンドル

低レベルネイティブプラグインインターフェース

基本的なスクリプトのインターフェースに加えて、プラグイン は Unity 上で発生したの特定のイベントをコールバックで受け取ることができます。これは主に、プラグインで低レベルのレンダリングを実装し、Unity のマルチスレッドレンダリングを操作できるようにするために使用されます。

Unity が提供しているインターフェースを定義するヘッダはエディターと一緒に提供されています。

インターフェース レジストリ

プラグインは、主要な Unity イベントを扱うために UnityPluginLoadUnityPluginUnload をエクスポートします。正しい署名は IUnityInterface.h で参照してください。 IUnityInterfaces は、追加的な Unity API にアクセスするためにプラグイン用に提供されています。

    #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>();
    }

グラフィックドライバへのアクセス

プラグインは、 IUnityGraphics インターフェースを取得することでジェネリックのデバイス機能にアクセスできます。旧バージョンの Unity では、 グラフィックス デバイス上のイベントに関する通知を受け取るには UnitySetGraphicsDevice 関数がエクスポートされる必要がありました。 Unity 5.2 からは、新しい IUnityGraphics インターフェース(IUnityGraphics.h にあります)によってコールバックを登録することが可能となっています。

    #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;
            }
        };
    }

レンダリングスレッド上のプラグインコールバック

Unity は当該プラットフォームでの CPU 数により実現できる範囲でレンダリングをマルチスレッド化することができます。マルチスレッドレンダリングを使うときレンダリング API コマンドは MonoBehaviour とは完全に別の、独立したスレッド上で実行します。そのため、いつでもプラグインからレンダリングを起動することが可能とは限りません。そして、レンダリングスレッドは干渉する可能性があります。

プラグインから どのような レンダリングを行う場合でも、プラグインはスクリプトから GL.IssuePluginEvent を参照しメインスレッドから呼び出されるようにする必要があります。例えば、カメラの OnPostRender 関数から GL.IssuePluginEvent を呼び出す場合、プラグインはカメラのレンダリング終了後すぐにコールバックを取得します。

UnityRenderingEvent コールバックの署名は IUnityGraphics.h で提供されています。 ネイティブプラグイン コードサンプル

    // 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;
    }

マネージドプラグイン コードサンプル

    #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);

このコールバックは CommandBuffer.IssuePluginEvent によって CommandBuffers に追加することもできます。

サンプル

低レベルレンダリングプラグインのサンプルを 2 つ紹介します。ここでダウンロードできます

  • すべての正規レンダリングが完了した後に、C++コードから回転する三角形を描画する
  • Texture.GetNativeTexturePtr を利用してアクセスし、C++のコードから手続き型テクスチャ( Procedural texture )を塗りつぶす

プロジェクトは以下で動作します。

  • プロジェクトは Windows ( Visual Studio 2013 )と MacOSX ( Xcode 3.2)で動作し、Direct3D 9、Direct3D 11、Direct3D 12、OpenGL のいずれかで使用しています。Direct3D 9 のコードは、“失われた” デバイスを処理する方法を示しています。
  • Windows Store Apps (詳細は RenderingPlugin\WSAVisualStudio2013 を参照してください)
デスクトップ向けのプラグインをビルド
アセットバンドル