Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve collision event support for common scenarios (minimal "kinematic bodies" support) #877

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

lostfictions
Copy link

@lostfictions lostfictions commented May 17, 2020

This PR allows static bodies to collide with each other, on the condition that at least one of the two is a sensor. It also allows static bodies to collide with sleeping bodies, though the latter won't automatically wake on such a collision. (They can just be woken in the collision event if needed; I do think it might be more intuitive for non-sensor static bodies to wake sleeping bodies automatically, but I'm not sure if that might carry undesirable side effects.)

Rationale

In games, even ones where gameplay is heavily driven by physics, it's often desirable to have full control over some physics bodies by removing the effect of simulation forces like gravity, drag, inertia, etc. on them. Some motion in games is highly unrealistic, so "doing one's own bookkeeping" on certain bodies can be more simple, predictable, and easy for designers to tweak than trying to wrestle with simulation properties. For example, in a game like Super Mario Bros you may want to limit terminal velocity to an explicit, fairly low value to allow players a chance to react even if they drop from a great height; or if the player bounces off a turtle you might not want to transfer momentum in a typical way.

That said, it's also often desirable for these manually-controlled bodies to continue to participate in the simulation in some way. If a simulation-driven rock falls on a character we may want them to take damage or otherwise react in some way; characters with skeletal animation may "ragdoll" and allow the simulation to dictate their motion. At a more basic level, it's useful to be able to reuse existing collision systems, events, and idioms rather than implement additional detection, spatial partitioning, etc., for this other class of objects.

Box2D, PhysX and other physics engines usually refer to this type of body as "kinematic," and it's one of the most upvoted issues for this repo. But Matter already has something very similar in isStatic: manually driving static bodies is very well-behaved, as the manipulation demo shows. The only thing missing is that currently only non-static bodies trigger events with static bodies, making it difficult to handle, say, the platform game case of an isStatic player character jumping on an isStatic enemy.

This PR resolves this by allowing pairs of static bodies to be candidates on the broadphase grid, as long as at least one of them is a sensor. This seemed like a reasonable compromise between allowing the necessary affordances for kinematic control without incurring too much of a performance penalty (or, I hope, introducing any unexpected new collision behaviour). It also removes an early out case in Detector.collisions (afaict never hit because of the broadphase condition) preventing two static bodies from colliding, and resolves an edge case where there wasn't really a sensible way for static bodies to wake sleeping dynamic bodies (fixes #875).

Alternatives

  • The Phaser game framework, which now bundles Matter, seems to suggest getting around the lack of static-on-static events by doing stuff like zeroing out gravity and setting inertia on bodies to infinity. This seems more inefficient -- since rather than telling the engine to not bother trying to apply forces, we're instead setting parameters high enough to make them moot -- and I worry it could lead to unexpected behaviour or simulation instability. It's also kind of inconvenient to have to zero out gravity and apply it ourselves, all else being equal.

  • Rather than making this new behaviour the default for static bodies, we could instead add a new per-body flag to opt-in to collisions with other static bodies. I think the "at least one sensor" approach of this PR is a good default, but a flag to allow a static body to collide with any other body (static or not, sensor or not) could still be useful on top of that. (Unity's 2D physics system, which is based on Box2D, has a per-body flag called "use full kinematic contacts" which does just this:)
    Screenshot from 2020-05-16 23-04-04

  • Rather than apply this behaviour to isStatic bodies, we could introduce a new kinematic body type. This doesn't seem super necessary to me, but it might make sense if there was further optimization work done on isStatic, such that it became a flag for bodies that were intended to never be moved or moved only infrequently. (It might also help alleviate some of the questions that come up in the issue tracker about kinematic bodies -- but updating demos or adding a bit more documentation could do that too.)

Hope this is helpful discussion! Sorry for the wall of text for such a tiny PR.

- support collision events when static bodies overlap static sensors
- support collision events when static bodies overlap sleeping bodies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Technique used in manipulation demo is insufficient to wake sleeping bodies
1 participant