从 C++ 本机插件更新 Vector3 数组
Update Vector3 array from C++ native plugin
Marshal.Copy()
方法只支持几种数组类型。现在我只知道如何从 IntPtr
(从 C++ 代码指向一个浮点数组)复制到 float[]
。
IntPtr pvertices = GetVerticesFromCPP();
float[] vertices = new float[nVertices * 3];
Marshal.Copy(pvertices, vertices, 0, nVertices * 3);
但我真正想要的是UnityEngine.Vector3[]
。
我需要手动将 float[]
转换为 UnityEngine.Vector3[]
吗?或者有没有更简单快捷的方法直接做到这一点?
Do I need to manually convert float[] to UnityEngine.Vector3[]? Or is
there a simpler and faster way that directly do this?
是的,您必须手动执行此操作,但有更好的方法来执行此操作。
我假设您需要在本机端修改 Vector3
然后 return 结果。不需要为此使用 float
数组。只需在 C++ 端创建一个 Vector3
结构,然后使用指针在 C++ 和 C# 之间传递它。 不要 return 来自 C++ 的 Vector3
数组 ,在 C# 端创建它,然后将它传递给 C++ 函数以修改并将更改应用到参数.
C++:
这需要您 Unity 中的 unsafe 关键字。
struct Vector3
{
float x;
float y;
float z;
};
那么你的函数:
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;
}
}
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);
}
}
}
用法:
从模型中获取顶点,发送到 C++ 并对其进行修改并重新分配修改后的网格:
void Start()
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
UpdateVectorArray(vertices);
//Re-assign the modified mesh
mesh.vertices = vertices;
mesh.RecalculateBounds();
}
要避免在 Unity 中使用 unsafe
关键字,请使用 [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();
}
C++ 方面保持不变。您也可以使用 固定数组并避免使用 unsafe
关键字,但 unsafe
关键字解决方案更好更快。
Marshal.Copy()
方法只支持几种数组类型。现在我只知道如何从 IntPtr
(从 C++ 代码指向一个浮点数组)复制到 float[]
。
IntPtr pvertices = GetVerticesFromCPP();
float[] vertices = new float[nVertices * 3];
Marshal.Copy(pvertices, vertices, 0, nVertices * 3);
但我真正想要的是UnityEngine.Vector3[]
。
我需要手动将 float[]
转换为 UnityEngine.Vector3[]
吗?或者有没有更简单快捷的方法直接做到这一点?
Do I need to manually convert float[] to UnityEngine.Vector3[]? Or is there a simpler and faster way that directly do this?
是的,您必须手动执行此操作,但有更好的方法来执行此操作。
我假设您需要在本机端修改 Vector3
然后 return 结果。不需要为此使用 float
数组。只需在 C++ 端创建一个 Vector3
结构,然后使用指针在 C++ 和 C# 之间传递它。 不要 return 来自 C++ 的 Vector3
数组 ,在 C# 端创建它,然后将它传递给 C++ 函数以修改并将更改应用到参数.
C++:
这需要您
struct Vector3
{
float x;
float y;
float z;
};
那么你的函数:
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;
}
}
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);
}
}
}
用法:
从模型中获取顶点,发送到 C++ 并对其进行修改并重新分配修改后的网格:
void Start()
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
UpdateVectorArray(vertices);
//Re-assign the modified mesh
mesh.vertices = vertices;
mesh.RecalculateBounds();
}
要避免在 Unity 中使用 unsafe
关键字,请使用 [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();
}
C++ 方面保持不变。您也可以使用 unsafe
关键字,但 unsafe
关键字解决方案更好更快。