I’m working on a game. I have a module I’ve named collision_manager. This modules stores objects in two arrays: bullets and enemies. I check for collisions between objects by looping though bullets with pairs(). With each bullet in the array I loop through all of the enemies in the enemy array and check for a collision between that bullet and each enemy.
This all works well. Then a problem occurs at some point where I get the following error:
ERROR: Attempt to remove an object that’s already been removed from the stage or whose parent/ancestor group has already been removed.
This can happen soon, or take a while, but always happens eventually. Obviously I’ve removed something and then tried to remove it again. I’m using a key type array to add each item to the array:
bullet_array[bullet] = bullet
And then removing items like this:
bullet_array[bullet] = nil
Seems like this should work, and it does work, for a while. I’m having trouble figuring out where it goes wrong. Any suggestions, I’m open to new ideas on how this might be improved.
Here’s a sample of the module code:
--------------------------------------------------- -- Collision Manager --------------------------------------------------- local M = {} local enemy\_array = {} local bullet\_array = {} -------------------------------------------------- local function hit\_test\_point( point, rect ) if point.x \> rect.l and point.x \< rect.r and point.y \> rect.t and point.y \< rect.b then return true else return false end end -------------------------------------------------- --------------------------------------------------- local function add\_enemy( enemy ) enemy\_array[enemy] = enemy end M.add\_enemy = add\_enemy --------------------------------------------------- local function add\_bullet( bullet ) bullet\_array[bullet] = bullet end M.add\_bullet = add\_bullet --------------------------------------------------- local function remove\_enemy( enemy ) enemy\_array[enemy] = nil end M.remove\_enemy = remove\_enemy --------------------------------------------------- local function remove\_bullet( bullet ) bullet\_array[bullet] = nil end M.remove\_bullet = remove\_bullet -------------------------------------------------- local function check\_enemies( bullet ) for enemy\_k, enemy in pairs( enemy\_array ) do if enemy ~= nil then local point = {x=bullet.x, y=bullet.y} local rect = {l=enemy.contentBounds.xMin, t=enemy.contentBounds.yMin, r=enemy.contentBounds.xMax, b=enemy.contentBounds.yMax} if hit\_test\_point( point, rect ) then remove\_bullet( bullet ) remove\_enemy( enemy ) bullet.remove\_bullet( bullet ) enemy.remove\_enemy( enemy ) end end end end local function check\_bullets() for bullet\_k, bullet in pairs( bullet\_array ) do if bullet.x ~= nil then check\_enemies( bullet ) end end end local function frame\_update() check\_bullets() end M.frame\_update = frame\_update --------------------------------------------------- return M