Physics not detecting collisions if I use filters

Ok so I have a simple set of filters for two objects and I use local collision detection. I create several objects and switch on debugging mode (hybrid). Each shape has a quad collision area but, in the simulator they push each other away even when not colliding. Then go to sleep once they seem to be far enough away.

If I add a filter which is literally this

physics.addBody( lock, “kinematic”, {density=0.1, friction=0, bounce=0,
shape={ -20,-20, 20,-20, 20,20, -20,20 },
filter={ categoryBits = 2, maskBits = 1},
} )

for one object and then this

physics.addBody( number, “dynamic”, {density=0, friction=0, bounce=0,
shape={ -10,-10, 10,-10, 10,10, -10,10 },
filter={ categoryBits = 1, maskBits = 2}
} )

for the second object. They never collide with one another. The lock object is static and the number is dynamic. At the start of the application I see the objects go to sleep. I then drag the number using a touch listener and the objects never wake again. Even if I force them awake in the moving phase, they never register a collision.

How is physics so broken? Or am I just missing something?

Edit: In fact a better question would be why do physics simply stop working once an object goes to sleep. The object never seems to be checked again regardless of what you do to it.

I tried an experiment and deliberately overlapped my filtered objects at start-up. lo and behold they register a collision. However, once the physics objects go to sleep. You can move them, set them awake etc. etc and they will never again register a collision or any physics activity.

How are you initiating the collisions? Dragging objects, unless using the setLinearVelocity, applyLinearImpulse or applyForce functions (within the Body function type), does not allow physics to act on objects. Therefore, no physics interactions will be registered.

Try this to test your physics:

physics.start() physics.setGravity( 0, 0 ) backg = display.newRect(-100,-100,1000,1000) local centertouchJump = function (event) if event.phase == "ended" then number:applyLinearImpulse(0, -10, number.x, number.y) return true end end Runtime:addEventListener( "touch", backg)  

Of course, this sends your object up in the air, so it might not work with your particular application. If you mess around with the numbers in the applyLinearImpulse parameters you should get what you’re looking for.

Gack! Thanks Panc!

So basically I can’t drag an object onto another object and have it simply register that the two are now colliding, without applying some force to the dynamic object. 

I changed the type to kinematic for the number and that too does nothing when I collide it with a static object manually. I always though the box2d was constantly checking for collisions regardless of how they occured but, clearly it is waiting for a force on the object to change before even bothering to check anything!

Surely this is a bug! If I set continuous check it should do just that, regardless of how the object is moving.

It’s definitely like that by design. Physics collisions are detected when an object interacts with another, because of physics.

However, there is a solution! Check the “non-physics collisions” tutorial that Rob Miracle threw together. I use it all the time, and it works like a charm.

Hi @danedwar, a few things to note:

  1. a collision will only occur between a dynamic body and another type of body (or another dynamic one). Never between two non-dynamic bodies. This is a rule regardless of anything else including awake state, collision filters, etc.

  2. if two bodies (sensors) are already overlapping, and one (or both) go to sleep, you can usually re-trigger a collision detection by force-waking it up and then setting “.isBodyActive” to true. This should “flash” the body’s sensory state and send back a collision response. You might, however, need to set “.isBodyActive” to false, then to true, in two consecutive lines… a little testing will be required to see which works.

Best regards,

Brent

Thanks Panc and Brent

Yea it looks like I’m just mis-understanding the box2d physics. I thought that, as long as the bodies were not both of the same type a collision should occur. Especially as kinematic bodies are designed to be moved via code. I therefore figured that this would mean that they should collide with both static and dynamic bodies i.e. fly a player controlled spacecraft into a wall and have it register.

One thing I do think is a bug though is that physics.start( true ) still seems to sleep all bodies just as though true was never passed. As does the flag on the actual body that says sleep isn’t allowed. Both of these states seem to simply be ignored. Do these flag not do what thought they were doing?

I’ve found that .isAwake=true works really well, especially in situations where the gravity might be changing but bodies will have gone to sleep:

https://docs.coronalabs.com/daily/api/type/Body/isAwake.html

It also doesn’t force objects to stay awake, unlike .isBullet

How are you initiating the collisions? Dragging objects, unless using the setLinearVelocity, applyLinearImpulse or applyForce functions (within the Body function type), does not allow physics to act on objects. Therefore, no physics interactions will be registered.

Try this to test your physics:

physics.start() physics.setGravity( 0, 0 ) backg = display.newRect(-100,-100,1000,1000) local centertouchJump = function (event) if event.phase == "ended" then number:applyLinearImpulse(0, -10, number.x, number.y) return true end end Runtime:addEventListener( "touch", backg)  

Of course, this sends your object up in the air, so it might not work with your particular application. If you mess around with the numbers in the applyLinearImpulse parameters you should get what you’re looking for.

Gack! Thanks Panc!

So basically I can’t drag an object onto another object and have it simply register that the two are now colliding, without applying some force to the dynamic object. 

I changed the type to kinematic for the number and that too does nothing when I collide it with a static object manually. I always though the box2d was constantly checking for collisions regardless of how they occured but, clearly it is waiting for a force on the object to change before even bothering to check anything!

Surely this is a bug! If I set continuous check it should do just that, regardless of how the object is moving.

It’s definitely like that by design. Physics collisions are detected when an object interacts with another, because of physics.

However, there is a solution! Check the “non-physics collisions” tutorial that Rob Miracle threw together. I use it all the time, and it works like a charm.

Hi @danedwar, a few things to note:

  1. a collision will only occur between a dynamic body and another type of body (or another dynamic one). Never between two non-dynamic bodies. This is a rule regardless of anything else including awake state, collision filters, etc.

  2. if two bodies (sensors) are already overlapping, and one (or both) go to sleep, you can usually re-trigger a collision detection by force-waking it up and then setting “.isBodyActive” to true. This should “flash” the body’s sensory state and send back a collision response. You might, however, need to set “.isBodyActive” to false, then to true, in two consecutive lines… a little testing will be required to see which works.

Best regards,

Brent

Thanks Panc and Brent

Yea it looks like I’m just mis-understanding the box2d physics. I thought that, as long as the bodies were not both of the same type a collision should occur. Especially as kinematic bodies are designed to be moved via code. I therefore figured that this would mean that they should collide with both static and dynamic bodies i.e. fly a player controlled spacecraft into a wall and have it register.

One thing I do think is a bug though is that physics.start( true ) still seems to sleep all bodies just as though true was never passed. As does the flag on the actual body that says sleep isn’t allowed. Both of these states seem to simply be ignored. Do these flag not do what thought they were doing?

I’ve found that .isAwake=true works really well, especially in situations where the gravity might be changing but bodies will have gone to sleep:

https://docs.coronalabs.com/daily/api/type/Body/isAwake.html

It also doesn’t force objects to stay awake, unlike .isBullet