If you want a true zero-allocation, zero-copy reinterpretation of an array of System.Numerics.Vector3 as an array of UnityEngine.Vector3, you need to use unsafe code to create a new view of the existing memory, but without creating a new array or copying the data.
In this solution, you will work directly with pointers to the memory where the array data is stored, essentially treating the System.Numerics.Vector3 array as if it were an array of UnityEngine.Vector3. The goal here is to re-use the exact same block of memory with no data movement.
Here’s how you can achieve this:
public class VectorInteropExample
public static unsafe UnityEngine.Vector3* ReinterpretVector3Array(System.Numerics.Vector3[] numericsArray)
// Pin the memory of the source array
var memoryHandle = numericsArray.AsMemory().Pin();
// Get a pointer to the start of the array data
void* pointer = memoryHandle.Pointer;
// Reinterpret the pointer as a UnityEngine.Vector3 pointer
return (UnityEngine.Vector3*)pointer;
public static unsafe void Main()
System.Numerics.Vector3[] numericsArray = new System.Numerics.Vector3[]
new System.Numerics.Vector3(1.0f, 2.0f, 3.0f),
new System.Numerics.Vector3(4.0f, 5.0f, 6.0f)
UnityEngine.Vector3* unityArrayPointer = ReinterpretVector3Array(numericsArray);
// Now we can access the Unity vectors directly using the pointer
for (int i = 0; i < numericsArray.Length; i++)
UnityEngine.Vector3 unityVector = *(unityArrayPointer + i);
Debug.Log($"Unity Vector {i}: {unityVector}");
numericsArray.AsMemory().Pin().Dispose(); // Dispose of the pinning handle.
-
Pinning the Array Memory:
- We pin the memory using
numericsArray.AsMemory().Pin().
- This ensures that the GC does not relocate the array in memory, which is crucial when working with raw pointers.
-
Unsafe Pointer Casting:
- We obtain a
void* pointer to the start of the array using memoryHandle.Pointer.
- We then cast this pointer to
UnityEngine.Vector3*.
- This allows us to directly access the
System.Numerics.Vector3 data as if it were an array of UnityEngine.Vector3, without making any copies.
-
No New Array Allocations or Data Copies:
- This approach does not create a new array or copy any data; instead, it directly reinterprets the existing data using pointers.
- You must work with the pointer, rather than creating a new array.
-
Accessing the Data:
- You can use pointer arithmetic to access individual elements of the array (
*(unityArrayPointer + i)).
- Since both
System.Numerics.Vector3 and UnityEngine.Vector3 share the same memory layout, this is valid.
-
Unsafe Code Requirements:
- This method requires the use of
unsafe code blocks.
- Your project needs to be configured to allow unsafe code (
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> in the .csproj file).
- Be cautious, as misuse of pointers can lead to undefined behavior, memory corruption, or crashes.
-
Memory Pin Management:
- It’s very important to properly manage the
memoryHandle to avoid memory leaks or unsafe memory access.
- In this example, I used
memoryHandle.Dispose() after you are done accessing the pointer to release the pinned memory.
This approach works well if you need to use the array purely in an unsafe context and are okay with directly handling pointers. You cannot safely return the raw pointer to other parts of the code unless the code continues to operate within an unsafe block.
Furthermore, keep in mind that working with pointers is inherently risky. Any misuse of pointers can lead to undefined behavior and can cause your application to crash. As such, it’s essential to ensure that you do not access memory beyond the bounds of the original array.