Physics not quite resetting

I’m having a strange issue where box2D isn’t resetting properly when you start the next level within the game (ie a “warm reset” within the programme I’m writing, I’m not talking about restarting the code). I’ve not had any problems with resetting the physics system in my previous projects, and I’m following the same method here, iterate through the table holding the bodies, destroy() each one, then nil the table, and then build the system again.

What happens with this project though, is in the first frame or two of the new game, I get a handful of collision events, say between five and twenty events, for bodies that don’t exist anymore. I need to check more, but it also seems that one or two of the new bodies have inherited the linear velocity of their predecessors. There is no evidence of “zombie” bodies though, no lingering rigid shapes in the field, as far as I can tell. It’s only an issue that affects the first frame or two. As each level starts with a “ready?” delay, I disable the collision checking for the duration of the delay, so the junk collisions aren’t so important. I’m worried that it could portend further problems down the line and I’m wondering what the cause could be.

There are a couple of things that I’m doing differently from previous projects, so they could be a culprit, but I haven’t been able to completely get rid of the problem.

  1. On “game over” I use physics:pause(). I want a freeze frame so the player can clearly see the game-ending event. I’ve experimented with using physics:resume() at various points, such as just before I destroy all the bodies, just after I destroy them, just as the new game is about to start etc. I’ve also tried removing the pause, resume calls altogether, but I still got the junk collisions.

  2. The second new process compared to what I’ve done before, is indexing the table holding the bodies by the body itself, an idea I “borrowed” from @Ignatz 's 2D sidescrolling platform game. It’s really handy for collisions, as you can call something like objects[contact.bodyA]:collide(contact) from the collision routine (…until you get collisions being triggered for bodies that don’t exist anymore upon the first frame or two of the restart)

  3. The events handler is also indexed in part by the body address. So there are at least three places pointing to the body. All of these tables get nilled when the game restarts though.

Could any of these things be keeping the bodies alive somehow?

I’ve read other threads about issues with resetting the physics, and tried things suggested there like running the entire destroy, create new bodies loop twice in a row, calling collectgarbage() after the tables have been destroyed, etc, but to no avail.

As I say, at the moment I have a delay as the physics starts, and that mostly deals with the issue, but it feels like a bit of a “bandaid” solution

@yojimbo2000 - I might start debugging by giving all the physics objects a name, via the info property, then when you get phantom collisions, you can print the names of the phantoms and at least see which they are.

PS I realise that pausing physics isn’t the main problem, but you could avoid the pause (in the interests of keeping things simple) when the level finishes, by redrawing the last frame to an image in memory, and spriting that as the frozen ending. Then you can delete all the objects behind the scenes.

@yojimbo2000 Are you destroying the objects in the table in reverse order. If you destroy an object in a table and remove that object from the table, the table shifts down and an object gets skipped each time. By doing it in reverse order, there is no shifting of the table.

@yojimbo2000, @dave1707 - I would do it more simply - loop through the table just destroying physics objects, then clear the table in one go with tableName={}. Then it doesn’t matter what order you use.

@yojimbo2000 I ran in to a similar problem in my game, where ghost objects would linger round. A lot of trial and error got me through it, if you like I could show you my strategy for setting up and removing entity tables properly in a big game. Without seeing code there is no positive assumption I can make.

I still say - first find out exactly which objects are zombies, then look at the way you are destroying them, and think about any other variables that may reference them.

@Ignatz Clearing the whole table works if the objects that are being destroyed are the only things in the table. Sometimes, a table can hold multiple objects and only certain objects in the table will be destroyed and removed. In that case, traversing the table in reverse order is the easiest way to delete and remove selected objects.

@dave1707 - I don’t disagree, there are lots of way to do these things

@Ignatz I agree. Without seeing the original code, we’re just guessing.

Here’s the reset code, fairly standard I think.
@Ignatz , yeah each body has an id string as its info. I get, say five to twenty junk collisions in the first frame or two of the restart. But other than that there aren’t zombie bodies or anything (it seems almost as if every collision from the previous game is replayed, all at once, in one frame).

Thinking about it, this is the first time I’ve used the game.bodies[contact.bodyA]:collide(contact) method of processing collisions, where each contact is tied to its iteration in the class. Maybe box2D always does this and I just haven’t noticed before.

   physics.resume() --to see if this is causing junk collision data in first frame of restart
    
    for i,v in pairs(game.bodies) do --table indexed by body memory address, therefore pairs
        v.body:destroy()
    end
    for i,v in ipairs(game.wall) do --except walls, indexed sequentially, therefore ipairs
        v:destroy()
    end
    
    game.events={} --these five lines are redundant, as game variable, and its arrays...
    game.bodies={}
    game.wall={}
    game=nil
    collectgarbage() 
    
    game=Game()  --...are reset here anyway
    game:initObjects()  --reboot game    


```

@yojimbo2000 - when you write this

for i,v in pairs(game.bodies) do 
    v.body:destroy()
end

is v a physics object? If it is, then you should destroy it with v:destroy() not v.body:destroy()

@Ignatz , no, with the game.bodies table self.body is the physics object, as there are all sorts of other variables associated with each iteration (a mesh, etc). With the game.wall table though, the self is the body, so it’s just v:destroy(). Here’s how each body is defined in its class:

    local b=physics.body(POLYGON, vec2(-ww,-ww),vec2(-ww,ww),vec2(ww,ww),vec2(ww,-ww))
    b.position=self.pos
    b.interpolate=true
    b.info=self.id
    self.body=b
    game.bodies[b]=self --indexed by body, useful for physics collisions

the last line is the technique I took from your 2D sidescroller.

For the game.bodies table, the command could even be i:destroy() as the index is also a pointer to the body.

This is slightly off-topic, but I was wondering, why is the body.info tag necessary? I’ve noticed that myBody behaves like any other table, that you can attach whatever arbitrary fields you want to it, myBody.foo="bar" or whatever, and that those user defined fields get passed to the collision routine, so you could query contact.bodyA.foo. So why a special info tag?

Convenience, I guess.

btw, you can’t use i:destroy(), it would have to be game.bodies[i]:destroy(), because i is not a pointer, but a table key.

@Ignatz But in this case the table key is the pointer. It was set as game.bodies[b]=self where b is the defined body. So the key is equal to (part of) the value, and in a pairs loop either key or value can be used (in this case either key or value.body).

Ah, yes

Great idea by the way, making the key the body memory address, thank you for that! Makes collision handling a breeze (from about frame 3 onwards…)

can you create a toy example that replicates the problem, then we have a chance of solving it with you

I think I’ve just worked it out! My brain must have been frozen.

I haven’t had a chance to test this hypothesis yet, but I think that this is what is happening. The physics body is created, and will start triggering collisions, as soon as the call to physics.body is made inside the class’s init() routine. But at this point, in the middle of the class init() function, there is not yet a self for that body, because the self is still in the process of being created (it doesn’t come into being until the end of the class init routine. To prove this: if you query objects[#objects] from within a class init routine, where objects is the table holding instances of that class, it will return the previously created instance, not the current self which is still under construction). So in my system collision events begin being triggered, but game.bodies[contact.bodyA]:collide(contact) in the collide function doesn’t work in frame 1, because game.bodies[contact.bodyA] doesn’t come into existence until frame 2.

So the solutions would be: first, just before the bodies are created in the init() routine, do some rough collision detection (not necessarily physics based, as the body in question doesn’t exist yet, just based on a calculation of “is distance greater than radius1+radius2”, and if so, move the coordinates of the new body slightly so it isn’t overlapping with anything).

But actually, my current “band aid” solution, of not calling the collision routine at all in frame 1, is probably the simplest fail-safe that will catch all occurrences.

I apologise if my previous posts implied that there was a fault with Box2D, when (as is almost always the case) the mistake is the user’s own.