In Unity 2019.3, there is the new Physics.BakeMesh API:
If I bake a mesh at runtime and assign it to a MeshCollider, do the cookingOptions in the MeshCollider have any affect? Do I need to set the MeshCollider.cookingOptions to None if I assign a baked mesh?
There seem to be no cookingOptions for Physics.BakeMesh?
The documentation reads:
I don’t understand this. When I assign a physics-baked mesh to a MeshCollider, what is being instantiated? I’m dynamically switching MeshCollider meshes at runtime, like through a flipbook. Would this cause any issues?
Let me go through some of the aspects of interaction with MeshCollider.
In practical terms, the most expensive function of MeshCollider is its sharedMesh property (MeshCollider::SetSharedMesh in the native lands if you examined the callstacks).
Changing sharedMesh might cause an expensive cooking/baking run. Whenever the sharedMesh property is changed, we will only reuse the PhysX mesh pointer stored in the Mesh instance if:
this MeshCollider’s cookingOptions are exactly the default ones, AND
the MeshCollider’s transform is good (*), AND
the Mesh instance hasn’t been changed since the last time cooking was ran.
(*) Here, MeshCollider’s transform is good when
it’s scaling is not negative and not skewed, OR
it’s scaling can be negative but only when MeshCollider is not convex
(Keep in mind that cooking requires the readable property of the Mesh set)
The cookingOptions are not stored in the Mesh instance, they belong to the MeshCollider instance currently. For that reason we will only write the PhysX mesh pointer back to Mesh if the cookingOptions are default.
Getting back to Physics.BakeMesh - it’s supposed to be used in conjunction with MeshColliders that have the default cooking options, as otherwise the PhysX mesh pointer won’t be shared.
I think there may actually be a bug in the code that performs the check related to this: - the Mesh instance hasn’t been changed since the last time cooking was ran.
From my experience, the actual behaviour is that the cooking/baking will be performed if the mesh was ever changed after it’s initial baking pass, regardless of whether it has changed since the last good bake.
// creating or refreshing mesh verts in job system
gameObject.SetActive(false);
collider.sharedMesh = null;
// creating or rebuilding mesh with new data
// setting mesh filter’s sharedmesh
gameObject.SetActive(true);
// Physics.BakeMesh( meshID ); in job system
collider.sharedMesh = mesh;
This seems to result in the following errors:
[Physics.PhysX] Foundation: Invalid deregistration detected. // on the null set
[Physics.PhysX] Foundation: Invalid registration detected. // on the refreshed mesh set
And to top it off, it seems to be rebaking the mesh anyways when setting the sharedMesh ;_;
May I kindly ask you to file a bug using Unity’s Bugreporter? You’d get a tracking link for this issue, and everyone will be able to track progress on it. Thanks!
Ever get a chance to look at this? I just updated to 2019.3.0f3 hoping it would be fixed, but I’m still seeing the bake show up in both the job system and the main thread… (schedules a job to bake a bunch of meshes, then next frame completes the job and sets the meshes to the sharedMesh parameter of their mesh colliders)
Oh, is the issue that a single mesh class instance being rebaked multiple times is not yet supported? I suppose I can work around this, although it does seem like a waste of heap space, in my case it may be acceptable as a workaround. I’ll try it, thanks!
I can confirm that currently it only seems to bake on fresh meshes. Can’t await the fix, i run a procedural Terrain-Generator on mobile:
I use custom meshes paired with Terrains that are only used for their TerrainColliders. Terrain Colliders can be updated about 10 times quicker than an equivalent CookingOption.None-meshcollider
(~1ms vs 10ms, cant be threaded → lags).
I already do threading on everything else, so finally having the option to thread mesh-collider generation is the best news ever! If this is fixed i can consider any mesh for my terrain, not just heightmapped terrains.
Question: are there any plans to expose the collider-data for a more direct tinkering? E.g. i could use the Terrain-Collider generation speed but with some flipped quads (for polystyle)
Is there any indication in the profiler if the mesh pointer can’t be shared with PhysX? I’m currently writing an import pipeline to create “physics meshes”, which are regular meshes ran through Physics.BakeMesh and saved as asset. I then assign these physics meshes to a MeshCollider at runtime and would like to know whether this works without overhead.
When you do get a chance to look deeper at this and work on fixing it, can you ensure that the previously baked collision mesh is still somehow valid until we swap to the new one? Or is it writing to the same buffer, so this is not possible? I may need to make a new mesh anyways (or I suppose, in the future just keep two and swap between them on update) to ensure collision is still valid while the new one is being baked…
I use transformations (including non-uniform scales) of a set of primitive MeshCollider objects to construct collision shape. I get colliders from pools). Needless to say, i’m getting a lot of Physics.Bake now left and right. It would be nice, if we could Physics.Bake(meshID, convex, transform) or Physics.Bake(meshID, convex, pos, rot, scale) if it has to be blittable.
Also - this fix can’t come fast enough. Creating new Mesh instances just because we need to change the mesh is insane.