onComplete removal function

Hello all,

I had a question regarding removing objects at the end of a transition and if / how those objects are released from memory. The function below seems to add another 2-3kb of memUsage every time one of these new animated objects are created (texture memory is holding steady). The memUsage never goes down as the objects are removed.

local function newEnergy()  
  
 -- spriteSheets located in a table earlier  
  
 local energy1set = sprite.newSpriteSet(spriteSheets["energy1"], 1, 9)  
 sprite.add(energy1set, "animateenergy", 1, 9, 750, 0 )  
  
 local function disperse(self)   
  
 -- Moves an energyball graphic a given distance and removes it after 3 seconds  
  
 self.transition = tnt:newTransition(self, {x = self.x + math.random(-400,400), y = self.y - 400, time = 3000,  
 onComplete = function() self:removeSelf() self = nil end })  
 end  
  
 local energy = sprite.newSprite(energy1set)  
 energy.x = crystal2.x  
 energy.y = crystal2.y  
  
 energy:prepare("animateenergy")  
 energy:play()  
 rearLayer:insert(energy)  
  
 disperse(energy)  
 return energy  
end  
  
local energyTimer = tnt:newTimer(1500, newEnergy, 0)  

Visually, this is working perfectly. I’m concerned about the creeping memory, however. I understand that I’m spawning these objects in a manner in which I lose the handle once they’re created. But I assumed it was fine since they are removed via a self-contained function. Am I incorrect? Is there a better way to do this?

-Brandon [import]uid: 136211 topic_id: 31476 reply_id: 331476[/import]

You seem to be creating a new spriteset on every newenergy this is likely to be eating memory. The spriteset should be outside the function as a global as its not changing.

Also setting self, a bad choice for a variable name btw, to nil has no effect. [import]uid: 74338 topic_id: 31476 reply_id: 125777[/import]

Thanks for the response. I certainly appreciate any and all feedback. Your idea to move the spriteSet out of the function was a good call.

However, renaming the “self” references to “obj” didn’t seem to make a difference in the memory usage. It still ticks up 2-3kb every new energy so I’m guessing the function at the end of that transition is failing to nil them out.

Also, how certain are you that “self = nil” has no effect? I learned the basics of Corona SDK from Rafael Hernandez’s video tutorial series and I know he used “self = nil” in a number of instances (I just confirmed from his “Balloon Burst” tutorial). Has this changed or was it a misunderstanding on his part?

Thanks again,

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125786[/import]

Hi Brandon,

I recommend that you move the removal function above and outside the newEnergy function, and call that function to remove the sprite.

You’re also creating a new sprite set every 1500 ms. You should create your sprite sets previously, and only add the actual sprites that are part of that set in a loop. This is probably why you’re getting memory creep.

Also, I notice you’re using the older, depreciated sprite library. While this is still allowed in Corona, I don’t recommend it unless your app is already considerably built using the older method and migrating to the new method is impractical or unrealistic.

I’m actually writing a tutorial about the new sprite setup which should be ready early next week, if you can wait that long to see how it’s done (certainly you can also follow the docs already online, if you want to dive right in!)

Brent [import]uid: 9747 topic_id: 31476 reply_id: 125802[/import]

Hi Brent,

I appreciate the advice. And it would take a miracle for me to publish within the next week so I think your tutorial on the new sprite set up will be very relevant for my project. I’m looking forward to it!

In regards to moving the removal function outside of the newEnergy function… I do believe you’ve likely identified the problem. I’ve noticed I have similar issues in other blocks of code when I use a similar method for object removal. It’s not working.

The challenge I’m having now is getting the outside removal function to acknowledge which object I’m trying to nil. It seems you can’t pass arguments / params thru an onComplete function at the end of a transition… at least not easily.

I’ve found some other forum posts relating to the issue but it’ll have to wait until morning. Thanks again for your help!

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125810[/import]

with regards passing functions to oncomplete, yes very easy - lookup lua closures :wink: [import]uid: 74338 topic_id: 31476 reply_id: 125832[/import]

Yep sure about this. lua passes by reference to functions - see code fragment below.
which means that setting the value of a passed in argument to nil shoould give nil as the second time I call my function

[lua]function mytest(paArray)
paArray = nil
print ( "setting value to nil " , paArray)
end

local myArr = {1,2,3,4,5,6,7}
print("before calling the function: ", myArr)
mytest(myArr)
print("after calling the function: ", myArr)[/lua]

when I run this I get

before calling the function: table: 01C71E68  
setting value to nil nil  
after calling the function: table: 01C71E68  

so very sure that your example of setting self to nil within the function achieves zilch.
whats going on is that your function is colliding with the reserved name - rather you should name your argument to functions so that they are distinct

I use the hungarian notation which includes scope, type and variable name which makes it really difficult to get the variables mixed up, which believe me is easy to do, I cant count the number of times I’ve dived into code and the function is using a variable with the same name as a variable in a higher scope - and the code doesnt do what its mean to do.

I wouldnt worry about the 2-3kb memory increase unless its really causing issues as it could be objects waiting to be garbage collected. You could force the gc with collectgarbage() to see how much memory there really is being used but that could cause performance problems. [import]uid: 74338 topic_id: 31476 reply_id: 125831[/import]

Hi Brandon,
It’s easy to pass the proper table identifier to a clear function after onComplete, you just need to know the proper “event” reference to it… that’s the tricky part. :slight_smile:

Here’s the clear function that I use. I put this far toward the top of my main.lua file so all following functions can access it. It clears objects both after a transition onComplete OR after a sprite animation onComplete (one with a frame listener).

In your case, the first two options won’t immediately apply, because you’re simply removing an object after a transition onComplete, which is the third case in the statement (default). But later, if you decide to clear an object after a sprite onComplete, i.e. when the animation reaches its final frame, you can use this same function to clear the sprite that way.

Of course, you might need to add a bit to this function if you’re storing objects in “holding tables” or referencing them elsewhere. For example, I put all of my animated sprites in a table so I can loop through that table on game pause (or un-pause), effectively pausing or un-pausing all sprites (there is no single command in Corona to pause every sprite, although I wish there was). So, I put those sprites into the holding table, and thus, when I clear them using the function below I must also remove them from that table or they’ll stick around in memory, per standard Lua behavior.

Anyway, this function has been very useful for me and I include it in all of my projects now, so I have a “one stop function” to clear objects following both transition complete and sprite listener complete.

local function clearObject( event )  
  
 local dstObj  
  
 if ( event.phase == "end" ) then --is a sprite (OLD sprite method)  
 dstObj = event.sprite  
 dstObj:removeEventListener( "sprite", clearObject )  
  
 elseif ( event.phase == "ended" ) then --is a sprite (CURRENT sprite method)  
 dstObj = event.target  
 dstObj:removeEventListener( "sprite", clearObject )  
  
 else  
 dstObj = event  
  
 end  
  
 if ( dstObj ) then display.remove( dstObj ) ; dstObj = nil end  
  
end  

Hopefully this proves useful to you too, and anybody else who wants to use it.
Brent [import]uid: 9747 topic_id: 31476 reply_id: 125849[/import]

Thanks again guys. This is great information and I appreciate you both taking the time to help me sort through this.

open768, your example with the mytest function is very interesting. It seems counterintuitive to me that something can exist, be nil, and immediately exist again. However, your example is very convincing. It’s as though the reference to the variable is getting nil’d but the variable itself doesn’t.

Brent, your idea for a one stop removal function is fantastic and I will definitely be implementing it (or a similar function like it). And I agree that a “pauseAll” command would be great for sprites.

Now, to do some research on closures and event references… :slight_smile:

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125858[/import]

You seem to be creating a new spriteset on every newenergy this is likely to be eating memory. The spriteset should be outside the function as a global as its not changing.

Also setting self, a bad choice for a variable name btw, to nil has no effect. [import]uid: 74338 topic_id: 31476 reply_id: 125777[/import]

Thanks for the response. I certainly appreciate any and all feedback. Your idea to move the spriteSet out of the function was a good call.

However, renaming the “self” references to “obj” didn’t seem to make a difference in the memory usage. It still ticks up 2-3kb every new energy so I’m guessing the function at the end of that transition is failing to nil them out.

Also, how certain are you that “self = nil” has no effect? I learned the basics of Corona SDK from Rafael Hernandez’s video tutorial series and I know he used “self = nil” in a number of instances (I just confirmed from his “Balloon Burst” tutorial). Has this changed or was it a misunderstanding on his part?

Thanks again,

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125786[/import]

Hi Brandon,

I recommend that you move the removal function above and outside the newEnergy function, and call that function to remove the sprite.

You’re also creating a new sprite set every 1500 ms. You should create your sprite sets previously, and only add the actual sprites that are part of that set in a loop. This is probably why you’re getting memory creep.

Also, I notice you’re using the older, depreciated sprite library. While this is still allowed in Corona, I don’t recommend it unless your app is already considerably built using the older method and migrating to the new method is impractical or unrealistic.

I’m actually writing a tutorial about the new sprite setup which should be ready early next week, if you can wait that long to see how it’s done (certainly you can also follow the docs already online, if you want to dive right in!)

Brent [import]uid: 9747 topic_id: 31476 reply_id: 125802[/import]

Hi Brent,

I appreciate the advice. And it would take a miracle for me to publish within the next week so I think your tutorial on the new sprite set up will be very relevant for my project. I’m looking forward to it!

In regards to moving the removal function outside of the newEnergy function… I do believe you’ve likely identified the problem. I’ve noticed I have similar issues in other blocks of code when I use a similar method for object removal. It’s not working.

The challenge I’m having now is getting the outside removal function to acknowledge which object I’m trying to nil. It seems you can’t pass arguments / params thru an onComplete function at the end of a transition… at least not easily.

I’ve found some other forum posts relating to the issue but it’ll have to wait until morning. Thanks again for your help!

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125810[/import]

with regards passing functions to oncomplete, yes very easy - lookup lua closures :wink: [import]uid: 74338 topic_id: 31476 reply_id: 125832[/import]

Yep sure about this. lua passes by reference to functions - see code fragment below.
which means that setting the value of a passed in argument to nil shoould give nil as the second time I call my function

[lua]function mytest(paArray)
paArray = nil
print ( "setting value to nil " , paArray)
end

local myArr = {1,2,3,4,5,6,7}
print("before calling the function: ", myArr)
mytest(myArr)
print("after calling the function: ", myArr)[/lua]

when I run this I get

before calling the function: table: 01C71E68  
setting value to nil nil  
after calling the function: table: 01C71E68  

so very sure that your example of setting self to nil within the function achieves zilch.
whats going on is that your function is colliding with the reserved name - rather you should name your argument to functions so that they are distinct

I use the hungarian notation which includes scope, type and variable name which makes it really difficult to get the variables mixed up, which believe me is easy to do, I cant count the number of times I’ve dived into code and the function is using a variable with the same name as a variable in a higher scope - and the code doesnt do what its mean to do.

I wouldnt worry about the 2-3kb memory increase unless its really causing issues as it could be objects waiting to be garbage collected. You could force the gc with collectgarbage() to see how much memory there really is being used but that could cause performance problems. [import]uid: 74338 topic_id: 31476 reply_id: 125831[/import]

Hi Brandon,
It’s easy to pass the proper table identifier to a clear function after onComplete, you just need to know the proper “event” reference to it… that’s the tricky part. :slight_smile:

Here’s the clear function that I use. I put this far toward the top of my main.lua file so all following functions can access it. It clears objects both after a transition onComplete OR after a sprite animation onComplete (one with a frame listener).

In your case, the first two options won’t immediately apply, because you’re simply removing an object after a transition onComplete, which is the third case in the statement (default). But later, if you decide to clear an object after a sprite onComplete, i.e. when the animation reaches its final frame, you can use this same function to clear the sprite that way.

Of course, you might need to add a bit to this function if you’re storing objects in “holding tables” or referencing them elsewhere. For example, I put all of my animated sprites in a table so I can loop through that table on game pause (or un-pause), effectively pausing or un-pausing all sprites (there is no single command in Corona to pause every sprite, although I wish there was). So, I put those sprites into the holding table, and thus, when I clear them using the function below I must also remove them from that table or they’ll stick around in memory, per standard Lua behavior.

Anyway, this function has been very useful for me and I include it in all of my projects now, so I have a “one stop function” to clear objects following both transition complete and sprite listener complete.

local function clearObject( event )  
  
 local dstObj  
  
 if ( event.phase == "end" ) then --is a sprite (OLD sprite method)  
 dstObj = event.sprite  
 dstObj:removeEventListener( "sprite", clearObject )  
  
 elseif ( event.phase == "ended" ) then --is a sprite (CURRENT sprite method)  
 dstObj = event.target  
 dstObj:removeEventListener( "sprite", clearObject )  
  
 else  
 dstObj = event  
  
 end  
  
 if ( dstObj ) then display.remove( dstObj ) ; dstObj = nil end  
  
end  

Hopefully this proves useful to you too, and anybody else who wants to use it.
Brent [import]uid: 9747 topic_id: 31476 reply_id: 125849[/import]

Thanks again guys. This is great information and I appreciate you both taking the time to help me sort through this.

open768, your example with the mytest function is very interesting. It seems counterintuitive to me that something can exist, be nil, and immediately exist again. However, your example is very convincing. It’s as though the reference to the variable is getting nil’d but the variable itself doesn’t.

Brent, your idea for a one stop removal function is fantastic and I will definitely be implementing it (or a similar function like it). And I agree that a “pauseAll” command would be great for sprites.

Now, to do some research on closures and event references… :slight_smile:

Brandon [import]uid: 136211 topic_id: 31476 reply_id: 125858[/import]