When returning false at beginCollision, it's called every step

Posts that don't fit into other categories.
soylomass
Posts: 22
Joined: Fri Nov 18, 2016 3:40 pm

When returning false at beginCollision, it's called every step

Postby soylomass » Wed Jan 24, 2018 6:32 pm

I noticed this behaviour some time ago, and I've since used a workaround for what I wanted to do.

If I remember right, in Box2d, even if your returned false for beginCollision, it wouldn't trigger the same event unless the bodies separated and started colliding again. But in Dyn4j if you return false, the collision chain is broken and restarted at every step, so there is no endCollision triggered, and beginCollision is called every time.

Is this behaviour normal?

PS: As a note, I use this when I need that a body collides physically with some other bodies, but doesn't with other, while still reporting the collision. So a sensor wouldn't be suitable here.

William
Site Admin
Posts: 377
Joined: Sat Feb 06, 2010 10:23 pm

Re: When returning false at beginCollision, it's called every step

Postby William » Wed Jan 24, 2018 10:20 pm

Yes, you are correct. That behavior is intentional, but not for the use case you describe.

While dyn4j shares a similar design, it's not a port so there will be differences in behavior. In this particular case I don't think there's any way to disable the contact for the timestep, but it wouldn't be hard to add it either and I can see how that would be useful.

The design of box2d was not a returned boolean but rather you'd set the enabled flag of the constraint to false inside the listener. dyn4j could take a similar approach without breaking the current behavior.

I will add this to the current set of changes that I have queued for release. Is this a time-sensitive request?

William

William
Site Admin
Posts: 377
Joined: Sat Feb 06, 2010 10:23 pm

Re: When returning false at beginCollision, it's called every step

Postby William » Thu Jan 25, 2018 12:06 am

Looking at this more, I'm wondering if it just makes more sense to use the returned value instead, breaking compatibility somewhat.

The current dyn4j code allows you to remove a contact from the contact constraint. For example, if two boxes are stacked there's 2 contact points that represent the "manifold" or "contact patch" of collision. I don't know if there's any benefit to that functionality tbh. You could do this in the CollisionListener methods anyway.

box2d retains the contact constraint in the contact manager when disabled, but doesn't include it during the solve step (its ignored during island generation). This allows the contact to not call the begin method over and over as you said.

In dyn4j, the ContactListener methods pass ContactPoint instances which are immutable and used for reporting only. Thus, there wouldn't be a way to set the enabled flag. The enabled flag could be set at the time the CollisionListener.collision(ContactConstraint) is called, but you wouldn't know whether it's a new contact or an existing one because the collision detection pipeline hasn't reached that point yet. Using the return value is a cleaner API as well. In addition, all the javadocs describe the return value as 'disabling' the contact, which could explain your confusion.

Practically speaking, changing this behavior to disable the contact constraint rather than removing a contact from it would likely produce the same simulation in most cases, but could produce a different one if user code was relying on the existing behavior.

I've commited a change to Git for this but haven't done any testing yet.

William

soylomass
Posts: 22
Joined: Fri Nov 18, 2016 3:40 pm

Re: When returning false at beginCollision, it's called every step

Postby soylomass » Thu Jan 25, 2018 8:06 am

Hi William, thanks for your quick response.

I've checked my previous game's code and you are right, the contact was disabled setting a flag on the Contact object, not returning false.

I think using the returned boolean to get the same behaviour as disabling the contact in Box2D would be a good idea, as if someone wanted to disable the contact but still be notified of the collision at every step he/she could use the persist method of the ContactListener (and it would be possible to enable the contact again returning true in this last method). At the same time, this would better linguistically speaking I think, because one would expect "begin" to be called only once when two bodies collide.

I understand that this will potentially cause unexpected behaviours for those who update and are already using ContactListener with the current functionality though.

PS: I saw the commit on the git, will test it.

William
Site Admin
Posts: 377
Joined: Sat Feb 06, 2010 10:23 pm

Re: When returning false at beginCollision, it's called every step

Postby William » Sat Apr 21, 2018 11:32 am

This change has been included in the 3.3.0 version of dyn4j.

Thanks,
William


Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 1 guest