从C ++本机插件更新Vector3数组

lan*_*ngs 3 c# c++ marshalling unity-game-engine

Marshal.Copy()方法仅支持几种数组类型。现在我只知道如何从IntPtr(指向C ++代码中的float数组)复制到float[]

IntPtr pvertices = GetVerticesFromCPP();
float[] vertices = new float[nVertices * 3];
Marshal.Copy(pvertices, vertices, 0, nVertices * 3);
Run Code Online (Sandbox Code Playgroud)

但是我真正想要的是一个UnityEngine.Vector3[]

我需要手动转换float[]UnityEngine.Vector3[]吗?还是有一种更简单,更快捷的方法直接做到这一点?

Pro*_*mer 7

我需要手动将float []转换为UnityEngine.Vector3 []吗?还是有一种更简单,更快捷的方法直接做到这一点?

是的,您必须手动执行此操作,但是有更好的方法可以执行此操作。

我将假定您需要Vector3在本机端进行修改,然后返回结果。不需要为此使用float数组。只需Vector3在C ++端创建一个结构,然后使用指针在C ++和C#之间传递它即可。不要Vector3从C ++ 返回数组,而是在C#端创建它,然后将其传递给C ++函数以修改并将更改应用于参数。

C ++:

这要求您在Unity中启用 unsafe关键字。

struct Vector3
{
     float x;
     float y;
     float z;
};
Run Code Online (Sandbox Code Playgroud)

然后你的功能:

extern "C" void UpdateVectorArray(Vector3* vecArray, int vecSize)
{
    for(int i = 0; i < vecSize; ++i)
    {
        //Simply modify each Vector reference
        Vector3 &vec = vecArray[i];
        vec.x = 11;
        vec.y = 20;
        vec.z = 55;
    }
}
Run Code Online (Sandbox Code Playgroud)

C#:

[DllImport("Plugin Name")]
static unsafe extern void UpdateVectorArray(Vector3* vecArray, int vecSize);


void UpdateVectorArray(Vector3[] vecArray)
{
    unsafe
    {
        //Pin array then send to C++
        fixed (Vector3* vecPtr = vecArray)
        {
            UpdateVectorArray(vecPtr, vecArray.Length);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

从模型获取顶点,发送到C ++并对其进行修改,然后重新分配修改后的网格:

void Start()
{
    Mesh mesh = GetComponent<MeshFilter>().mesh;

    Vector3[] vertices = mesh.vertices;
    UpdateVectorArray(vertices);

    //Re-assign the modified mesh
    mesh.vertices = vertices;
    mesh.RecalculateBounds();
}
Run Code Online (Sandbox Code Playgroud)

为了避免unsafe在Unity中使用关键字,请使用[In, Out] 属性。

[DllImport("Plugin Name")]
static extern void UpdateVectorArray([In, Out] Vector3[] vecArray, int vecSize);

void Start()
{
    Mesh mesh = GetComponent<MeshFilter>().mesh;

    Vector3[] vertices = mesh.vertices;
    UpdateVectorArray(vertices, vertices.Length);

    mesh.vertices = vertices;
    mesh.RecalculateBounds();
}
Run Code Online (Sandbox Code Playgroud)

C ++方面仍然相同。您也可以使用GCHandle固定数组,避免使用 unsafe关键字,但是unsafe关键字solution更好,更快。