Unity の ネイティブプラグイン は、特定のイベントが発生したときにコールバックを受け取ることができます。これを利用して、プラグインに低レベルレンダリングを実装し、Unity のマルチスレッドレンダリングと連携できます。
Unity のメインイベントを処理するために、プラグインは UnityPluginLoad
と UnityPluginUnload
関数をエクスポートする必要があります。IUnityInterfaces はプラグインがこれらの関数にアクセスすることを可能にします。IUnityInterfaces はプラグイン API の IUnityInterface.h
にあります。
# include "IUnityInterface.h"
# include "IUnityGraphics.h"
// Unity プラグイン load イベント
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
IUnityGraphics* graphics = unityInterfaces->Get<IUnityGraphics>();
}
IUnityGraphics.h
にある IUnityGraphics
インターフェースを使用すると、プラグインが汎用グラフィックスデバ イス機能にアクセスできるようになります。このスクリプトは、IUnityGraphics
インターフェースを使用して、コールバックを登録する方法を示します。
# include "IUnityInterface.h"
# include "IUnityGraphics.h"
static IUnityInterfaces* s_UnityInterfaces = NULL;
static IUnityGraphics* s_Graphics = NULL;
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
// Unityプラグインロードイベント
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
s_UnityInterfaces = unityInterfaces;
s_Graphics = unityInterfaces->Get<IUnityGraphics>();
s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);
// グラフィックデバイスがすでに初期化されている場合にイベントを見逃さないようにするため
// プラグインのロード時に手動で OnGraphicsDeviceEvent(initialize) を実行する。
OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}
// ユニティプラグインのアンロードイベント
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();
//ユーザー初期化コード記入
break;
}
case kUnityGfxDeviceEventShutdown:
{
s_RendererType = kUnityGfxRendererNull;
//ユーザーシャットダウンコード記入
break;
}
case kUnityGfxDeviceEventBeforeReset:
{
//ユーザーの Direct3D 9 コード記入
break;
}
case kUnityGfxDeviceEventAfterReset:
{
//:ユーザーの Direct3D 9 コード記入
break;
}
};
}
プラットフォームと使用可能な CPU の数が許す限り、Unity でマルチスレッドを使用してレンダリングすることができます。
ノート: マルチスレッドレンダリングを使用すると、レンダリング API のコマンドは、MonoBehaviour スクリプトを実行するスレッドとは完全に別のスレッドで実行されます。メインスレッドとレンダースレッドの間で通信が行われるため、メインスレッドがレンダースレッドに渡した作業量によっては、プラグインがすぐにレンダリングを開始しない場合があります。
プラグインからレンダリングするには、マネージプラグインスクリプトから GL.IssuePluginEvent を呼び出します。これにより、下のコード例に示すように、Unity のレンダーパイプラインは、レンダースレッドからネイティブ関数を呼び出します。例えば、Camera の OnPostRender 関数から GL.IssuePluginEvent を呼び出すと、この関数は、カメラがレンダリングを終了するとすぐにプラグインコールバックを呼び出します。
ネイティブプラグインのコード
// 特定のレンダリングイベントを処理するプラグイン関数
static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
{
//ユーザーのレンダリングコード
}
// プラグイン特有のスクリプトにコールバックを渡すための自由に定義した関数
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();
// 指定のコールバックがレンダースレッドで呼び出されるようにキューで待機
GL.IssuePluginEvent(GetRenderEventFunc(), 1);
UnityRenderingEvent
コールバックのシグネチャは、Native Rendering Plugin サンプルの IUnityGraphics.h で提供されています。
OpenGL オブジェクトには 2 種類あります。
Unity は複数の OpenGL コンテキストを使用します。エディターとプレイヤーの起動と終了時にはマスターコンテキストに依存し、レンダリング時には専用のコンテキストを使用します。つまり、 kUnityGfxDeviceEventInitialize
と kUnityGfxDeviceEventShutdown
イベント中にコンテキストごとのオブジェクトを作成することはできません。
• 2017–05–16 修正されたページ