I recently spent some time porting an in-development game from 2.4 to 3.0. I've been really enjoying the new shapes and the more detailed b2DebugDraw (the debug visualization for contacts and joints is super useful), and it's reassuring to have multithreading as an option now even if we might not end up needing it. For the most part things worked without much debugging, but there were a few pain points I ran into in the process, and I figured it might be helpful to leave some feedback about them:
There's no built-in way to iterate the contacts of a sensor, which makes sensors significantly less useful.
I understand that you want people to use contact events for performance reasons, but it's a much less natural way of expressing certain kinds of game logic. Querying "what is overlapping this shape" and iterating the results is one of the most common things I do in gameplay code, and using sensor events makes this kind of code much less clear to read and write. An alternative, and what I'm doing currently, is to emulate sensor collision detection using an overlap query to get a list of contacts, but it's a significant chunk of code and the performance seems to be worse than iterating the contact list used to be in 2.4, which makes sense given that it sort of defeats the point of having the sensor be a persistent shape participating in collision detection in the first place. On the other hand, overlap queries also allow detecting kinematic-vs-kinematic and kinematic-vs-static shape overlaps, which is potentially useful, so in some ways maybe it's better.
The solver reports almost-but-not-quite-touching contacts with larger slop than in 2.4 (seems to be a few centimeters now, whereas before iirc it was under 1cm)
I trust that for solver accuracy this doesn't cause any problems, but it means users who want contact detection accuracy below a few centimeters need to check the contact manifold separation for each contact they get back from b2Body_GetContactData().
There's no built-in function to compute the mass / mass data of a shape.
It's not too difficult to write a helper function that gets the underlying primitive and calls the appropriate b2Compute*Mass() function for it, but this feels like something that should be built-in, like it was for fixtures in 2.4.
It's unclear what positions to give for support points for non-looping chains that do not connect to another chain.
Neither the API comments nor the documentation pages give any guidance on this that I could find. This was already somewhat of a problem before, but certain configurations that were fine in 2.4 have bad behavior now with circles and rounded shapes. The new solver seems to be much more picky about this. I had to use trial and error to figure out that I needed the support point to form a highly acute angle to get good collision with the edges of chain shapes, and although I think I understand why now after playing with it, it would be nice to have this explained in the documentation somewhere.
For reference on why collision with chain edges is relevant, we often end up with collision geometry like this, where two different chain edges meet at a point, which we want to treat the same as a corner:
I suppose it's probably possible to detect these situations and fix up the support points automatically, or add editor functionality to specify support points and line them up by hand, which is probably the most principled solution, but it's nicer to not have to worry about these things if we can avoid it.
Overlaps get resolved very slowly.
For all cases I tested, but specially between dynamic bodies, it's way slower than in 2.4. It used to take a few ticks for bodies to get pushed out of each other, whereas now it often takes an entire second for them to slowly get pushed out. Setting a higher contactPushoutVelocity in the world definition seems to have no effect on this at all.
The approximation used for computing mass data for rounded polygons can overestimate or underestimate by a significant amount.
An accurate area at least could be calculated by adding perimeter * radius + pi * radius^2 to the base polygon area if I'm not mistaken, but I don't know whether there is a simple or efficient way to accurately compute the center of mass and rotational inertia, so this may not be a straightforward thing to fix.
The API comments and migration guide should be more clear that b2Body_GetContactData() can return fewer than b2Body_ContactCapacity() results.
The doc pages explain this, but the other sources don't mention it. It's quite easy to accidentally read garbage / uninitialized / stale contact data if you miss that detail.
The lack of gear joints.
It's probably possible to emulate the behavior of these in user code, but I assume it would be more performant/robust/accurate to do it in the solver. I remember you mentioned in a blog post that you wanted to rework gear/pulley joints, so just take this as me saying that I'm looking forward to them.
I recently spent some time porting an in-development game from 2.4 to 3.0. I've been really enjoying the new shapes and the more detailed b2DebugDraw (the debug visualization for contacts and joints is super useful), and it's reassuring to have multithreading as an option now even if we might not end up needing it. For the most part things worked without much debugging, but there were a few pain points I ran into in the process, and I figured it might be helpful to leave some feedback about them:
There's no built-in way to iterate the contacts of a sensor, which makes sensors significantly less useful.
I understand that you want people to use contact events for performance reasons, but it's a much less natural way of expressing certain kinds of game logic. Querying "what is overlapping this shape" and iterating the results is one of the most common things I do in gameplay code, and using sensor events makes this kind of code much less clear to read and write. An alternative, and what I'm doing currently, is to emulate sensor collision detection using an overlap query to get a list of contacts, but it's a significant chunk of code and the performance seems to be worse than iterating the contact list used to be in 2.4, which makes sense given that it sort of defeats the point of having the sensor be a persistent shape participating in collision detection in the first place. On the other hand, overlap queries also allow detecting kinematic-vs-kinematic and kinematic-vs-static shape overlaps, which is potentially useful, so in some ways maybe it's better.
The solver reports almost-but-not-quite-touching contacts with larger slop than in 2.4 (seems to be a few centimeters now, whereas before iirc it was under 1cm)
I trust that for solver accuracy this doesn't cause any problems, but it means users who want contact detection accuracy below a few centimeters need to check the contact manifold separation for each contact they get back from
b2Body_GetContactData()
.There's no built-in function to compute the mass / mass data of a shape.
It's not too difficult to write a helper function that gets the underlying primitive and calls the appropriate
b2Compute*Mass()
function for it, but this feels like something that should be built-in, like it was for fixtures in 2.4.It's unclear what positions to give for support points for non-looping chains that do not connect to another chain.
Neither the API comments nor the documentation pages give any guidance on this that I could find. This was already somewhat of a problem before, but certain configurations that were fine in 2.4 have bad behavior now with circles and rounded shapes. The new solver seems to be much more picky about this. I had to use trial and error to figure out that I needed the support point to form a highly acute angle to get good collision with the edges of chain shapes, and although I think I understand why now after playing with it, it would be nice to have this explained in the documentation somewhere.
For reference on why collision with chain edges is relevant, we often end up with collision geometry like this, where two different chain edges meet at a point, which we want to treat the same as a corner:
I suppose it's probably possible to detect these situations and fix up the support points automatically, or add editor functionality to specify support points and line them up by hand, which is probably the most principled solution, but it's nicer to not have to worry about these things if we can avoid it.
Overlaps get resolved very slowly.
For all cases I tested, but specially between dynamic bodies, it's way slower than in 2.4. It used to take a few ticks for bodies to get pushed out of each other, whereas now it often takes an entire second for them to slowly get pushed out. Setting a higher
contactPushoutVelocity
in the world definition seems to have no effect on this at all.The approximation used for computing mass data for rounded polygons can overestimate or underestimate by a significant amount.
An accurate area at least could be calculated by adding
perimeter * radius + pi * radius^2
to the base polygon area if I'm not mistaken, but I don't know whether there is a simple or efficient way to accurately compute the center of mass and rotational inertia, so this may not be a straightforward thing to fix.The API comments and migration guide should be more clear that
b2Body_GetContactData()
can return fewer thanb2Body_ContactCapacity()
results.The doc pages explain this, but the other sources don't mention it. It's quite easy to accidentally read garbage / uninitialized / stale contact data if you miss that detail.
The lack of gear joints.
It's probably possible to emulate the behavior of these in user code, but I assume it would be more performant/robust/accurate to do it in the solver. I remember you mentioned in a blog post that you wanted to rework gear/pulley joints, so just take this as me saying that I'm looking forward to them.
Thanks for making box2d!