composer question about removing scene and objects

I was wondering how important object:removeSelf() actually is when using composer.

I have a game where you control 4 hero’s and you play through a level fighting multiple enemies.

When an enemy defeats one of my hero’s I currently use the Hero1:removeSelf() and then promptly after, I use Hero1 = nil as instructed in the tutorial: https://coronalabs.com/blog/2012/07/03/properly-removing-objects-and-variables/

I have found though, that this causes issues with my enemy objects. They mainly use a runtime function that tracks the location of the Hero’s then move to that location and start to attack. If suddenly one of the Hero’s become nil it throws a lot of things off.

Reading into composer I figured that composer.removeScene would eventually remove all objects on the screen once I leave the level, so I was wondering if anyone had some insight on how important it is to use object:removeSelf()

I figure if I can avoid the removeSelf() I can just move the dead hero’s from sight and it would be much easier to handle that way.

Thanks

You can just 

display.remove(hero)

Don’t nil it.

I just found that more efficient.

You can do “composer.removeScene()” but i found that to not really work when i didn’t add the object into self.view. When i had to resort to that solution I ended up throwing my self back into the code and properly getting all the object and actually properly removing them.

That said: That blog was written 3 years ago.

But you can check if the object exists or not so when the hero dies the enemy checks that the hero is dead and moves on with his life.

Any display object that you have added to the Composer scene’s “view” group (i.e. sceneGroup, self.view or scene.view depending on where you are scope wise) will be removed for you automatically when either:

  1. composer.removeScene(“yourSceneInQuestion”) is called.

  2. You have setup composer to auto dump scenes when you leave them. (https://docs.coronalabs.com/api/library/composer/recycleOnSceneChange.html)

  3. You have setup processes do dump scenes when the memory is low. (https://docs.coronalabs.com/api/library/composer/recycleOnLowMemory.html)

In the case for #1. You don’t need to remove the objects yourself. Composer takes care of that for you. In the process, it will call your scene:destroy() event function, which is a place to dispose of audio you may have loaded during scene:create() or close databases/files you may have opened earlier. This function gets called well after your scene is no longer on screen.

Timers, physics, transitions, music etc. should be stopped/cancelled in scene:hide() since you don’t want them running  after the scene leaves the screen (and conversely to make things line up right, those things should only be started in scene:show() or user action after the scene is on screen and running.

If you do call display.remove( someObject ), you should still nil out someObject.

Now to the OP’s real issue.

If you are holding a reference to an object in multiple places, you have to nil it out in multiple places:

hero = display…

enemy.targetedHero = hero

display.newImageRect() (or whatever display object you’re using) returns a pointer to a table that contains the object. Lets say the memory address for that table is 0x9483a122. The two lines of code above have basically created a simple variable named hero that contains the value 0x483a122. When you assign hero to enemy.targetedHero, you’re simply copying the value from here to the enemy.targetedHero attribute.

Now you come along and do either:

hero:removeSelf()

hero = nil

or

display:remove( hero )

hero = nil

The memory allocated to that table/object including the texture memory is freed up. The simple variable hero is now nil and no longer points to a memory address. All is happy. Except for the fact that enemy.targetedHero still contains the value 0x483a122 and thinks it’s pointing to a valid display object.

Your runtime function that’s looking at the enemy’s reference still thinks its good, when it’s not an your app blows up. Hiding the object if it’s not a lot of memory/resources is a perfectly valid method for this. If you need to bring that hero back, you can reset any values that need to be. Position it where you want it, make it visible again.

But you might want to make sure that if you go the remove method (needed if you’re eating a lot of memory or have a lot of objects), to make sure to clear all your references to the object.

Rob

If you do call display.remove( someObject ), you should still nil out someObject.

@Rob. What’s the point of 

object = nil

Every time I used it; it didn’t make difference. Although it might vary from situation to situation?  I mostly make apps and small one touch games for clients so nil’ing doesn’t seem to make a difference for me.

It has to do with how modern operating systems manage memory. In the old C malloc/free days, this would probably be fine. And to over simplify the description, there is something called ARC or automatic reference counting. The program keeps track of memory and the way Lua garbage collects, it’s not released immediately. It won’t be reclaimed until all references to the memory are released. The act of nil’ing an object decrements the reference counting. Later when GC runs and memory has been marked to be freed up and nothing is left pointing to it, it gets reclaimed.

Rob

Thanks Rob, I do make sure to add all my objects into the sceneGroup = self.view for composer thus, when I destroy a scene its sure to clean it all up. I dont think that it would take up too much memory just to hide the objects. I’ll run with that for now and hopefully I dont run into issues in the future.

You can just 

display.remove(hero)

Don’t nil it.

I just found that more efficient.

You can do “composer.removeScene()” but i found that to not really work when i didn’t add the object into self.view. When i had to resort to that solution I ended up throwing my self back into the code and properly getting all the object and actually properly removing them.

That said: That blog was written 3 years ago.

But you can check if the object exists or not so when the hero dies the enemy checks that the hero is dead and moves on with his life.

Any display object that you have added to the Composer scene’s “view” group (i.e. sceneGroup, self.view or scene.view depending on where you are scope wise) will be removed for you automatically when either:

  1. composer.removeScene(“yourSceneInQuestion”) is called.

  2. You have setup composer to auto dump scenes when you leave them. (https://docs.coronalabs.com/api/library/composer/recycleOnSceneChange.html)

  3. You have setup processes do dump scenes when the memory is low. (https://docs.coronalabs.com/api/library/composer/recycleOnLowMemory.html)

In the case for #1. You don’t need to remove the objects yourself. Composer takes care of that for you. In the process, it will call your scene:destroy() event function, which is a place to dispose of audio you may have loaded during scene:create() or close databases/files you may have opened earlier. This function gets called well after your scene is no longer on screen.

Timers, physics, transitions, music etc. should be stopped/cancelled in scene:hide() since you don’t want them running  after the scene leaves the screen (and conversely to make things line up right, those things should only be started in scene:show() or user action after the scene is on screen and running.

If you do call display.remove( someObject ), you should still nil out someObject.

Now to the OP’s real issue.

If you are holding a reference to an object in multiple places, you have to nil it out in multiple places:

hero = display…

enemy.targetedHero = hero

display.newImageRect() (or whatever display object you’re using) returns a pointer to a table that contains the object. Lets say the memory address for that table is 0x9483a122. The two lines of code above have basically created a simple variable named hero that contains the value 0x483a122. When you assign hero to enemy.targetedHero, you’re simply copying the value from here to the enemy.targetedHero attribute.

Now you come along and do either:

hero:removeSelf()

hero = nil

or

display:remove( hero )

hero = nil

The memory allocated to that table/object including the texture memory is freed up. The simple variable hero is now nil and no longer points to a memory address. All is happy. Except for the fact that enemy.targetedHero still contains the value 0x483a122 and thinks it’s pointing to a valid display object.

Your runtime function that’s looking at the enemy’s reference still thinks its good, when it’s not an your app blows up. Hiding the object if it’s not a lot of memory/resources is a perfectly valid method for this. If you need to bring that hero back, you can reset any values that need to be. Position it where you want it, make it visible again.

But you might want to make sure that if you go the remove method (needed if you’re eating a lot of memory or have a lot of objects), to make sure to clear all your references to the object.

Rob

If you do call display.remove( someObject ), you should still nil out someObject.

@Rob. What’s the point of 

object = nil

Every time I used it; it didn’t make difference. Although it might vary from situation to situation?  I mostly make apps and small one touch games for clients so nil’ing doesn’t seem to make a difference for me.

It has to do with how modern operating systems manage memory. In the old C malloc/free days, this would probably be fine. And to over simplify the description, there is something called ARC or automatic reference counting. The program keeps track of memory and the way Lua garbage collects, it’s not released immediately. It won’t be reclaimed until all references to the memory are released. The act of nil’ing an object decrements the reference counting. Later when GC runs and memory has been marked to be freed up and nothing is left pointing to it, it gets reclaimed.

Rob

Thanks Rob, I do make sure to add all my objects into the sceneGroup = self.view for composer thus, when I destroy a scene its sure to clean it all up. I dont think that it would take up too much memory just to hide the objects. I’ll run with that for now and hopefully I dont run into issues in the future.