Removing complex objects from memory

Hi,

In my game, we use quite often decorate display objects with functions and some properties.
Most often display object become quite complex, mostly because they also contain other display objects.

In other words, I’ve got helper functions, which produce parts of my game, like:
an enemy, which is a group, with animation, with health bar [which is also a display object] etc.
So the enemy will be decorated with references to those objects, because I interact with them, so I don’t want to go looking for them through the whole table of objects in a group, only to change a value or do something else.
Then again, because I hold a reference to those objects it becomes difficult to properly get rid of them from memory.
Simply because when i do enemy:removeSelf() it will only remove the group, the animation, health bar etc references will be held on the object thus will remain in memory.

In many places [on many objects] I’ve created a custom “remove” function, which [should] properly clean up the object. Unfortunately, this function has to be called manually, so if I’ve got a group “enemyGroup” which contains all of the enemies, and this enemyGroup is within actionGroup which contains enemies and objectiles used to destroy those enemies, and I remove actionGroup by doing actionGroup:removeSelf() I’m screwed.

Some time ago, I’ve found, that my custom remove() functions are called from somewhere within Corona [stack trace won’t tell me where from, but not within my code]. I had to rename them to something like removeEnemy() or removeWhatever().

I couldn’t find any mention of this, but I;m wondering if this is documented somewhere, that when display object is removed, it will call a remove() function if one exists. That would solve some of my problems.

The other thing I think about is to actually remove all of the references and try to find proper objects within groups. This however, might cost me a lot of loops, especially that my enterFrame functions are quite overloaded.

Anyway… could someone give me a hint on how to properly remove complex objects?
Please, don’t point me toward coronalabs/ansca blog entries about display objects removal, as the examples are only valid for very flat object hierarchies.

To wrap things up, I would like to easily remove objects like this:

local test = display.newGroup()  
test.text1 = display.newText("whatever", 0, 0, system.nativeFont, 12)  
test:insert(test.text1)  
test.text2 = display.newText("whatever2", 0, 0, system.nativeFont, 14)  
test:insert(test.text2)  
test.text2.boom = function(val)  
 -- my imagination doesn't run that deep today  
end  
test.somethingElse = display.newGroup()  
test.somethingElse.rect = display.newRect(0, 0, 500, 500)  
test.somethingElse:insert(test.somethingElse.rect)  
test.somethingElse = { val1 = 124, val2 = 1234 }  
local test2 = display.newGroup()  
test2:insert(test)  

it’s just a pseudo structure, something to give you an idea.

[import]uid: 109453 topic_id: 33153 reply_id: 333153[/import]

@krystian6,

  1. As far as I know, there is no automatic onRemove() or other scripted event that occurs when a display object is removed.

  2. I’m 99% sure you can make a Lua object notify you when or as it is removed. Also, when Corona SDK removes display objects it does make certain changes like removing the removeSelf() function, etc.

As I understand it, when you call removeSelf() (and I think when a object is removed in general) there is a point where that object replaced with a plain Lua table.

I occasionally wonder about ways to make automatically called onRemove() functions. One article here (by Jonathan Beebe) touched on concepts that might be used to do this: http://www.coronalabs.com/blog/2012/05/01/tutorial-property-callbacks/
3. For your specific example. I don’t think it is as complex as the stuff that is giving your problems. You can remove most everything you created like this:
[lua]test2:removeSelf()
test2 = nil
test = nil[/lua]

As long as you insert all of the objects you created into test and then inserted test into test2, removing test2 and clearing the two variables test and test2 will do it. The only case where you get yourself in trouble is where you didn’t add test.somethingElse* into the group.

If you get really desperate, you could always do something like this:

[lua]local garbage = {}

… further on in your code

local test1 = display.*() - Some function that creates something.
garbage[test1] = test1

local test2 = display.*() - Some function that creates something.
garbage[test2] = test2

local testN = display.*() - Some function that creates something.
garbage[testN] = testN

– Just keep adding stuff to garbage()

– Later, you can remove everything safely like this:
for k,v in pairs( garbage ) do
– Check if,
– This object exists, is a display object, and hasn’t been removed yet.
– The function removeSelf will not exist if the object was removed already.
– (Head nod to robmiracle for this way of checking for a valid display object.)
if(v.removeSelf and type(v.removeSelf) == “function”) then
v:removeSelf()
end
end
garbage = nil[/lua]

[import]uid: 110228 topic_id: 33153 reply_id: 132030[/import]

@krystian6,

  1. As far as I know, there is no automatic onRemove() or other scripted event that occurs when a display object is removed.

  2. I’m 99% sure you can make a Lua object notify you when or as it is removed. Also, when Corona SDK removes display objects it does make certain changes like removing the removeSelf() function, etc.

As I understand it, when you call removeSelf() (and I think when a object is removed in general) there is a point where that object replaced with a plain Lua table.

I occasionally wonder about ways to make automatically called onRemove() functions. One article here (by Jonathan Beebe) touched on concepts that might be used to do this: http://www.coronalabs.com/blog/2012/05/01/tutorial-property-callbacks/
3. For your specific example. I don’t think it is as complex as the stuff that is giving your problems. You can remove most everything you created like this:
[lua]test2:removeSelf()
test2 = nil
test = nil[/lua]

As long as you insert all of the objects you created into test and then inserted test into test2, removing test2 and clearing the two variables test and test2 will do it. The only case where you get yourself in trouble is where you didn’t add test.somethingElse* into the group.

If you get really desperate, you could always do something like this:

[lua]local garbage = {}

… further on in your code

local test1 = display.*() - Some function that creates something.
garbage[test1] = test1

local test2 = display.*() - Some function that creates something.
garbage[test2] = test2

local testN = display.*() - Some function that creates something.
garbage[testN] = testN

– Just keep adding stuff to garbage()

– Later, you can remove everything safely like this:
for k,v in pairs( garbage ) do
– Check if,
– This object exists, is a display object, and hasn’t been removed yet.
– The function removeSelf will not exist if the object was removed already.
– (Head nod to robmiracle for this way of checking for a valid display object.)
if(v.removeSelf and type(v.removeSelf) == “function”) then
v:removeSelf()
end
end
garbage = nil[/lua]

[import]uid: 110228 topic_id: 33153 reply_id: 132030[/import]