Unity中的C#与C++交互

来源:互联网 发布:架子鼓软件 编辑:程序博客网 时间:2024/06/11 18:41

参考:Unity Manual-Low-level Native Plugin Interface

源码demo 


演示了一个渲染三角形的例子 
C++部分代码实现了对底层API的封装以及核心功能实现。

RenderingPlugin.cpp中定义了C++的接口。其中定义了一系列全局变量,用户通过接口函数对这些全局变量赋值。如: 
设定纹理

// --------------------------------------------------------------------------// SetTextureFromUnity, an example function we export which is called by one of the scripts.static void* g_TextureHandle = NULL;static int   g_TextureWidth  = 0;static int   g_TextureHeight = 0;extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetTextureFromUnity(void* textureHandle, int w, int h){    // A script calls this at initialization time; just remember the texture pointer here.    // Will update texture pixels each frame from the plugin rendering event (texture update    // needs to happen on the rendering thread).    g_TextureHandle = textureHandle;    g_TextureWidth = w;    g_TextureHeight = h;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Plugin装载与卸载

static IUnityInterfaces* s_UnityInterfaces = NULL;static IUnityGraphics* s_Graphics = NULL;extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces){    s_UnityInterfaces = unityInterfaces;    s_Graphics = s_UnityInterfaces->Get<IUnityGraphics>();    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);    // Run OnGraphicsDeviceEvent(initialize) manually on plugin load    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);}extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload(){    s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

渲染线程的回调函数

static void UNITY_INTERFACE_API OnRenderEvent(int eventID){    // Unknown / unsupported graphics device type? Do nothing    if (s_CurrentAPI == NULL)        return;    DrawColoredTriangle();    ModifyTexturePixels();    ModifyVertexBuffer();}// --------------------------------------------------------------------------// GetRenderEventFunc, an example function we export which is used to get a rendering event callback function.extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc(){    return OnRenderEvent;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

DrawColoredTriangle是渲染的处理函数,分别针对不同的底层API进行封装,如

RenderAPI_D3D11.cppRenderAPI_D3D12.cppRenderAPI_OpenGL2.cpp
  • 1
  • 2
  • 3

C#为了调用plugin专门做一层封装,见UseRenderingPlugin.cs

引用dll中的方法

    // We'll also pass native pointer to a texture in Unity.    // The plugin will fill texture data from native code.#if (UNITY_IPHONE || UNITY_WEBGL) && !UNITY_EDITOR    [DllImport ("__Internal")]#else    [DllImport ("RenderingPlugin")]#endif    private static extern void SetTextureFromUnity(System.IntPtr texture, int w, int h);#if (UNITY_IPHONE || UNITY_WEBGL) && !UNITY_EDITOR    [DllImport ("__Internal")]#else    [DllImport("RenderingPlugin")]#endif    private static extern IntPtr GetRenderEventFunc();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

调用C++中的SetTextureFromUnity函数

    private void CreateTextureAndPassToPlugin()    {        // Create a texture        Texture2D tex = new Texture2D(256,256,TextureFormat.ARGB32,false);        // Set point filtering just so we can see the pixels clearly        tex.filterMode = FilterMode.Point;        // Call Apply() so it's actually uploaded to the GPU        tex.Apply();        // Set texture onto our material        GetComponent<Renderer>().material.mainTexture = tex;        // Pass texture pointer to the plugin        SetTextureFromUnity (tex.GetNativeTexturePtr(), tex.width, tex.height);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

渲染线程注册C++的回调函数

private IEnumerator CallPluginAtEndOfFrames()    {        while (true) {            // Wait until all frame rendering is done            yield return new WaitForEndOfFrame();            // Set time for the plugin            SetTimeFromUnity (Time.timeSinceLevelLoad);            // Issue a plugin event with arbitrary integer identifier.            // The plugin can distinguish between different            // things it needs to do based on this ID.            // For our simple plugin, it does not matter which ID we pass here.            GL.IssuePluginEvent(GetRenderEventFunc(), 1);        }    }
原创粉丝点击