Page 1 of 1

Collision callback returns error: "Box2D assertion failed""

Posted: Thu Sep 15, 2022 10:32 pm
by Sammm
Hello!

I'm trying to handle collisions between the player and spikes, and when the player collides with the spikes, reset the player position. Here's my code for handling the collision, using callbacks:

Code: Select all

function beginContact(a, b, coll)
	if a:getUserData() == "Player" and b:getUserData() == "Spikes" then
		player.body:setPosition(player.x, player.y)
	end
end
However, when I run it, it works fine, but when the player collides with the spikes, I get an error, stating:
Error

main.lua:225: Box2D assertion failed: m_world->IsLocked() == false


Traceback

[C]: in function 'setPosition'
main.lua:225: in function <main.lua:223>
[C]: in function 'update'
main.lua:161: in function 'update'
[C]: in function 'xpcall'
I know the collision works fine normally, before I tried to reset the player's position, I printed a line to the console and everything worked fine. It's the "setPosition()" function that's somehow giving me an error. Here's the zip file with the code (I'm still trying to figure out how to make a .love file, sorry).
game.zip
(1.24 MiB) Downloaded 48 times
Thanks for any help! :)

Re: Collision callback returns error: "Box2D assertion failed""

Posted: Fri Sep 16, 2022 1:28 am
by Ross
Check the warning on the World:setCallbacks() page:
Making changes to a World is not allowed inside of the beginContact, endContact, preSolve, and postSolve callback functions, as Box2D locks the world during these callbacks.
It's a bit of a nuisance, but that's just how it works, which is understandable, since modifying things while the physics engine is in the middle of resolving collisions would really throw a wrench in the works.

I deal with it with a simple delayed callback setup. Inside the callbacks, if I want to do something that may modify the physics world, I instead just add the function and its arguments to a table, then after world:update() is done, I go through the list of delayed callbacks (if any) and call them.

Also of note from the docs:
The Contacts may be destroyed immediately after the callback is called, so if you want to store their data for use later in love.update, you must cache it.
In other words: you can't save the Contact itself for later, if you need the contact normal or something, you need to get it from the Contact during the physics callback and save that data for use later.