kikito / bump.lua

A collision detection library for Lua
MIT License
922 stars 86 forks source link

Item Object must be added to the world before getting its rect. #32

Closed voronianski closed 7 years ago

voronianski commented 7 years ago
2017-01-09 00 30 55

This strange error happens to me in very rare cases randomly. I remove bullets when they are out of visible camera - https://github.com/voronianski-on-games/asteroids-on-steroids-love2d/blob/master/src/bullet.lua#L55-L62

kikito commented 7 years ago

What that error means is that you are calling world:getRect on an item which has already been removed from the world. Seeing your trace, it seems that getRect is called from world:remove. So this seems to indicate that you are calling world:remove more than once. Try printing "destroying " .. self.created_at inside Entity:destroy - if you see calls to that method with the same created_at, that's your problem.

The exact reason why this happens is difficult to say without me actually downloading your game and debugging it, but honestly I have no time to do that (sorry).

A quick-and-probably-dirty-and-wrong way to solve this could be putting an if inside Entity:destroy using world:hasItem, like so:

function Entity:destroy ()
  if self.world:hasItem(self) then
    self.world:remove(self)
  else
    print("Tried to remove already removed object: " .. self.created_at)
  end
end

This might make the game work, but it would be masking the problem, not solving it. Chances are it would resurface again in another place (if you are trying to remove already removed objects, you will probably also try to draw them, etc). Maybe applying this patch and seeing this error pop up somewhere else will give you a clue to find the real problem.

Let me stress out that this is supposed to be a temporary thing; you should get to the root problem and solve that.

DanielPower commented 7 years ago

I struggled with this issue in my game as well. It is not an issue with bump, but with your removal code.

I had this issue when I was calling self:destroy() on my instances when they collided with a wall. But if the instance had hit a corner so that it touched two walls at the same time, self:destroy() was called twice in the same frame.

I got around this by using a garbage collection table. When I destroyed an object, I would first iterate through the trash table, and make sure that object was not already in the trash table. If not, I added it to the trash table. Then, at the end of the game loop, I would destroy all of the objects in the trash table, and empty the trash table.

That way everything only got destroyed once, even if there were two conditions for its destruction in the same frame.