Version: 5.3 (switch to 5.4b)
Сборка плагинов для настольных платформ
AssetBundles

Нативный низкоуровневый интерфейс плагина

В дополнение к основному интерфейсу скриптов Native Code Plugins Unity может принимать запросы и вызовы, когда происходят какие-либо события. Обычно это используется для низкоуровневого рендеринга в вашем плагине, а также позволяет работать с многопоточными процессами рендеринга 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>();
    }

Доступ к графическому устройству

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

Вызовы плагина из потока рендеринга

Рендеринг в Unity может быть многопоточным, если позволяет используемая платформа и количество доступных для него процессоров. Когда используется многопоточный рендеринг, команды API рендеринга выполняются в потоке, который полностью отделен от того, который запускает сценарии MonoBehaviour. Следовательно, ваш плагин не всегда сможет начать рендеринг немедленно, так как ему может помешать общий поток отрисовки, выполняемый в это время.

Для того чтобы сделать какой-либо рендеринг из плагина, вы должны вызвать GL.IssuePluginEvent из скрипта, который вызовет ваш плагин из потока отрисовки. Например, если вы вызовите GL.IssuePluginEvent из функции камеры OnPostRender, то получите обратный вызов плагина сразу же после завершения обработки камеры.

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

Such callbacks can now also be added to CommandBuffers via CommandBuffer.IssuePluginEvent.

Пример

Пример плагина низкоуровневого рендеринга можно скачать здесь. В нём продемонстрированы два аспекта:

  • Изображение вращающегося треугольника из кода C++ после завершения всех процессов рендеринга.
  • Заполнение процедурной текстуры из кода C++, используя Texture.GetNativeTexturePtr для доступа.

Проект работает с:

  • Windows (Visual Studio 2008) и Mac OS X (Xcode 3.2) и использует Direct3D 9, Direct3D 11 или OpenGL, в зависимости от платформы. Direct3D 9 часть кода также демонстрирует как управлять “потерянными” устройствами.
  • Windows Store Apps, (см. RenderingPlugin\WSAVisualStudio2012 для получения большей информации)
Сборка плагинов для настольных платформ
AssetBundles