When to dispose NativeArray<> and when *not* to.

Obviously, I should dispose a NativeArray<> I allocate.

But if I assign it to a Mesh – Mesh.SetBoneweights() – should I dispose it?

Or, if I get a NativeArray from a Mesh – Mesh.GetBoneWeights() – should I dispose it?

Because sometimes I do this, and get an error “InvalidOperationException: The NativeArray can not be Disposed because it was not allocated with a valid allocator”

Seems like that means I shouldn’t right? But sometimes I don’t get that.

Now, I ALWAYS check “IsCreated()” before disposing. So if you don’t want me to dispose it, why set that to true?
Is there another flag somewhere that says “Hey, you should dispose this”.

Because otherwise, I can’t figure it out.

See, when I load the items from addressables, it gives the “memory leak” message for not disposing them, even though I HAVE disposed them, and validated every allocate with a dispose.

Please help a guy out here.

You always need to dispose any native containers you allocate, unless it’s allocated with “Temp”. Any data you pass to a mesh gets copied, so yes, you still need to dispose them.

If you use Temp or TempJob allocate when you need it and dispose as soon as you are done with it. Their usage is for one frame (though I guess TempJob allows 4 frames before giving error?).

You shouldn’t need to check for IsCreated() for that, though I don’t your usage of NativeArray with Addressables. Maybe you need to use Persistent allocator.

Did you mean Mesh.GetBoneAllWeights() ?

Most of the api’s using native containers have you pass in one that you allocate. Ones that just return a native collection like that really should take an Allocator you provide. If they don’t you should check the allocator yourself to see what type it is. Probably Temp but I would explicitly check.

Also Unity - Manual: NativeContainer has some information at the bottom, except it’s actually wrong about Temp needing disposing.

Yeah, Mesh.GetAllBoneWeights and Mesh.GetBonesPerVertex. I can’t see a way to pass an allocator to them, or to check the allocator on the returned object. I was basically using the IsCreated() flag to see if it needed to be cleaned.
(Documentation states: “Indicates that the NativeArray has an allocated memory buffer” – which, I assumed that items that were pointers into an existing array, or which referred to memory was not allocated for me, would return false.) But that’s not true.

I don’t even understand the point of the exception. They provide a Dispose() method. It should be safe to call it whether or not they want to free the memory. Dispose is basically: “Hey, I’m done. Cleanup what you need to clean up”. It doesn’t mean “Hey, go free all your memory whether it needs to be or not”.

According to the source the arrays you get from those functions are retrieved via “ConvertExistingDataToNativeArray” with the allocator being “None”. Based on that I would guess you’re not meant to dispose them, they’re just giving you a read-only view into the data while avoiding allocations.

I feel like the documentation should be much more clear any time a Unity function returns a native array so we know exactly what we’re getting. In general it’s safe to assume if you’re getting a native array from a function and not passing an allocator, you don’t need to dispose it.

3 Likes

My bad I was thinking collections had an Allocator property.

@Sarkahn_1 beat me to it. They are wrapping an existing internal buffer. But you really should be able to determine that at the code level in some way like being able to retrieve the allocator type. Docs would help but docs are not good enough here.

2 Likes