Convert a pinned managed array to NativeArray (Getting CheckElementReadAccess error)

Hello Community,

am having a system where I’m manipulating a mesh through a DLL on C++ side. The mesh vertices are sent via a pinned GCHandle gained like:
GCHandle.Alloc(mesh.vertices, GCHandleType.Pinned);
This works are expected.
However now I would also like to read those same vertices array with burst, thus needing a native array - WITHOUT COPYING (since this is for procedural terrain generation in realtime hence why doing the heavy lifting in C++).

The method NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray seemed perfect for that and an example like this (unrelated to meshes now) compiles, given unsafe context:

                Vector3[] my_verts = new Vector3[100];
                my_verts[0] = new Vector3(17, 3, 9);

                // Convert the managed array to a NativeArray (without copying the data)
                GCHandle mesh_vertices_gc = GCHandle.Alloc(my_verts, GCHandleType.Pinned);
                IntPtr ptr = mesh_vertices_gc.AddrOfPinnedObject();
                NativeArray<Vector3> nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector3>((void*)ptr, 100, Allocator.None);

                Debug.Log("PTR : " + ptr); // A valid looking adress
                Debug.Log("Length: " + nativeArray.Length); // 100 -> correct

However trying to access nativeArray[0] results in:

Somebody know what I am missing here?

Huge thanks in advance!

ConvertExistingDataToNativeArray for some reason doesn’t set the AtomicSafetyHandle. If you are using the Collections package, there’s a helper in there that will do that correctly.

Also, is there a reason you aren’t using the MeshData API for this?

Huge thanks! That was the right thing.

Well, the C++ side of this system was designed before the new MeshData api existed unfortunately and switching is not so easy since from what I see it puts everything related to a vertex (xyz, UV, normals) in one single consecutive array instead of separate arrays.


That said, turns out if I use Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle, the project doesn’t build anymore.
This thread here claims that’s even intended: https://discussions.unity.com/t/873713
Any idea on this?

EDIT:
Can’t even steal the handle of another NativeArray because “SetAtomicSafetyHandle” as a whole is unavailable in builds!

You have to wrap all stuff using AtomicSafetyHandle in a ENABLE_UNITY_COLLECTIONS_CHECKS block.

Just found that out too… after trying the opposite and activating COLELCTIONS_CHECKS via define.
Alright, that all makes sense now.