PolygonCollider2D.SetPath from Unsafe Arrays fast and without GC

Hey there, I’m trying to get full polygon collision on my terrain, it’s working pretty well so far but now I’m trying to optimize it.


The points from the path are generated in a job. Inside the job unsafe lists are created and I need to send those to the PolygonCollider2D as fast as possible and hopefully without GC. I managed to get it working fast, but I just can’t find a way to get rid of the GC alloc.

public void ApplyColliderTask ()
{
    collider.enabled = false;
    collider.pathCount = paths.Length;
    for (int i = 0; i < paths.Length; i++)
    {
        Vector2[] points = new Vector2[paths[i].Length];

        unsafe
        {
            fixed (void* pointsPointer = points)
            {
                UnsafeUtility.MemCpy(pointsPointer, paths[i].Ptr, paths[i].Length * sizeof(float) * 2);
            }
        }

        collider.SetPath(i, points);
        paths[i].Dispose();
    }
    collider.enabled = true;
}

Here’s what I’ve got so far, I create c# arrays (which I’m trying to avoid) and then I copy the content of the unsafe array over to the c# array using the UnsafeUtility.MemCpy. Then I can finally call collider.SetPath.

Is there any way to reuse the same array somehow? Or maybe some kind of way to send a native array to collider.SetPath? If only fixed worked with list.

Setting it via NativeArray isn’t there but there’s an overload to accept both array and List. If you were to use/reuse the List then you’d only ever allocate if you increased the capacity of the list.

Adding in the ability to set via NativeArray is coming in later versions of Unity.

Also, if you can do the decomposition of the outline paths using a 3rd party utility then it’d be much faster using the CustomCollider2D which can do changes in realtime.

I would like to use lists but I got two problems,

  • How do I do a fast copy from unsafe array to list
  • How to I actually change the “count” of the list after copying the data

I’ve tried googling for that but the solutions seemed old and not really suited for my specific needs.

And I don’t know any 3rd party shape decomposition sadly, and I don’t want to waste my precious time making one that will probably end up slower than what I currently have.

Ah right, I didn’t follow what you meant by this, seems you meant the overload that accepts List I mentioned.

Unfortunatley you’re correct in that cannot get a fixed pointer to a list so there isn’t a way to do a memcpy AFAIK although that part isn’t my area of expertise; maybe someone else will jump in there.

Could you afford to sacrifice the memcpy for a element by element copy into those lists therefore avoiding GC hits? Not the best but better than lots of GC potentially and feasible if you don’t have thousands of points or this isn’t happening at a high frequency.

Eventually you’ll be able to do this but unfortunately not now.

As long as native array support is planned later in the future (we’ll probably release the game in more than a year if everything goes well), I think I’ll just take the hit of the element->element copy.

1 Like