Memory usage keeps rising when switching between scenes HELP

Hi all,

I have been trying to get storyboard working but have had some difficulties with the memory. I have set up below two simple screens that when pressed switch between the two screens to one another (back and forth). I am tracking the memory usage with a function in the main lua file. I believe I am following everything correctly but I still see that memory usage rises as I switch back and forth. Could someone please help explain what I am doing wrong.

Thanks,
Chris

[lua]–Main.lua



– main.lua


local storyboard = require “storyboard”

– Remove Status Bar –
display.setStatusBar( display.HiddenStatusBar )

local monitorMem = function()
collectgarbage()
print( "MemUsage: " … collectgarbage(“count”) )

local textMem = system.getInfo( “textureMemoryUsed” ) / 1000000
print( "TexMem: " … textMem )
end

Runtime:addEventListener( “enterFrame”, monitorMem )

storyboard.gotoScene( “loadingScreenOne” )

– loadingScreenOne.lua

local loadingImage;
local pressed

function scene:createScene( event )
local group = self.view

end

function scene:enterScene( event )
local group = self.view

loadingImage = display.newImageRect(“images/loadingScreen1.png”, 480, 320);
loadingImage.x = 240; loadingImage.y = 160;

group:insert(loadingImage);

pressed = function(e)
if (e.phase == “ended”) then
storyboard.gotoScene(“loadingScreenTwo”);
end
end

loadingImage:addEventListener(“touch”, pressed);

end

function scene:exitScene( event )
local group = self.view

loadingImage:removeEventListener(“touch”, pressed);

end

function scene:destroyScene( event )
local group = self.view

end

scene:addEventListener( “createScene”, scene )

scene:addEventListener( “enterScene”, scene )

scene:addEventListener( “exitScene”, scene )

scene:addEventListener( “destroyScene”, scene )

return scene

–loadingScreenTwo.lua

local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

local loadingImage2
local pressed

function scene:createScene( event )
local group = self.view

end

function scene:enterScene( event )
local group = self.view

loadingImage2 = display.newImageRect(“images/loadingScreen2.png”, 480, 320);
loadingImage2.x = 240; loadingImage2.y = 160;

group:insert(loadingImage2);

pressed = function(e)
if (e.phase == “ended”) then
storyboard.gotoScene(“loadingScreenOne”);
end
end

loadingImage2:addEventListener(“touch”, pressed);
end

function scene:exitScene( event )
local group = self.view

loadingImage2:removeEventListener(“touch”, pressed);

end

function scene:destroyScene( event )
local group = self.view

end

scene:addEventListener( “createScene”, scene )

scene:addEventListener( “enterScene”, scene )

scene:addEventListener( “exitScene”, scene )

scene:addEventListener( “destroyScene”, scene )

return scene

[import]uid: 126017 topic_id: 28556 reply_id: 328556[/import]

Your destroyScene isn’t destroying anything, so when switching back and forth between scenes, your images are being added again and again to your groups.

[lua]function scene:destroyScene( event )
local group = self.view
group:removeSelf()
group = nil
end[/lua]

Also, do a removeAll in your create scene so that you’re sure the other screens get destroyed

[lua]storyboard.removeAll()[/lua]

HTH :slight_smile: [import]uid: 144908 topic_id: 28556 reply_id: 115094[/import]

The memory increase is because you are doing all of your scene creation in “enterScene” rather than “createScene”.

Storyboard attempts to cache scenes for efficiency. That is if you have SceneA and SceneB, if SceneA calls SceneB, SceneA is not automatically removed, bit its retained in memory so that when SceneB goes back to SceneA, it doesn’t have to recreate the scene.

createScene is only called if the scene does not exist.
enterScene is called whenever you do a storyboard.gotoScene. If it doesn’t exist, createScene is called first. If it does exist, we go directly to enterScene.

When you call another scene, the current scene’s exitScene is called. destroyScene is only called under two conditions: 1. A low memory warning will cause storyboard to remove all active scenes in which case this scene’s destroyScene is called. 2. If you do a storyboard.removeScene or .removeAll.

Since you do no work in createScene, every time you reenter your scene, you recreate all the assets again and you are never destroying them.

You have two choices. Move all of the scene construction code to createScene where it belongs and then let the system (or your own remove calls) clean up previous scenes. Or do as the post above suggests and put a:

group:removeSelf()
group = nil

In the exitScene. The former is the recommended way to do it, the later is more Director like. [import]uid: 19626 topic_id: 28556 reply_id: 115136[/import]

i didnt spot the error in enterScene x_x.

+1 to robmiracle [import]uid: 144908 topic_id: 28556 reply_id: 115212[/import]

Thanks a lot to all the responses this really helped me understand it better. I have fixed the code and there are no memory leaks anymore.

Best,

Chris [import]uid: 126017 topic_id: 28556 reply_id: 115224[/import]

These explanations do help me understand Storyboard better. Thank you.

For even more clarity, would somebody please give examples of what would typically be put in createScene vs. what would be put in enterScene? There are a few in the Corona template, but more specifics would be very helpful.

Many thanks in advance.

-Mat [import]uid: 70259 topic_id: 28556 reply_id: 115418[/import]

createScene should get anything that needs to be displayed when the scene starts and probably anything that you will display later (but starting hidden) that you can create at the beginning.

enterScene should start any animatons, timers, and add any Runtime event handlers… Thinks like touch handlers on objects can be done in createScene since they are automatically destroyed when the object is destroyed.

enterScene would also initialize any variables that would need set when you leave the scene and then come back later. Any thing that doesn’t need re-initialized probably should be done in createScene.
Then in removeScene, you would manually remove any event listeners you created in enterScene, as well as all timers and transitions that are going on.

Finally in destroyScene, you would remove anything you created in createScene that you DID NOT put into the “group” display group. I rarely if ever put anything in here because I should not be creating any display objects in a scene that will persist from scene to scene. Those probably should be created in main.lua and shown and hidden as necessary.

The reason for this is if you’re in scene2 after having visited scene1 and a low memory event happens, scene1 gets purged, but those display items still showing would get recreated when you revisit scene1 over top of the ones you have already created and not destroyed. i.e. memory leak. [import]uid: 19626 topic_id: 28556 reply_id: 115432[/import]

@Mat, imagine you had a tableview that loads data from a webservice like a twitter feed. In createScene you would put the code to create the tableview and other UI elements and in enterScene you might put the code to get the tweets from the webservice and update the cells in the tableview. This way every time the user goes to that scene the data gets updated and you don’t need to load all the UI elements again.

^ Is this correct too robmiracle? [import]uid: 58885 topic_id: 28556 reply_id: 115437[/import]

Thank you for taking the time to answer. These explanations help a lot. [import]uid: 70259 topic_id: 28556 reply_id: 115564[/import]

what if I create objects in enterScene and insert them into group ( self.view ), should I not insert them into the group and destroy them in exitScene OR I have to insert them into the group and in

group:removeSelf()  

they will cleaned as well ?


what about spritesheets, I create them in createScene and add them all into group ( self.view), should I clean them too ?

[import]uid: 138983 topic_id: 28556 reply_id: 118055[/import]

Does a person have to explicitly call these in the destroyScene event?

group:removeSelf()
group = nil

I thought that was the point of storyboard… but I guess I’ve been missing a big part of it?
Is there a way to manually trigger the destroyScene event so that a person can verify their code their works?

[import]uid: 105707 topic_id: 28556 reply_id: 118511[/import]

No, you do not need to remove group and nil it. Storyboard handles that for you. [import]uid: 19626 topic_id: 28556 reply_id: 118555[/import]

@robmiracle

Thanks for confirming that. At what point does that happen? The destroyScene event?

I really thought I was finally getting my head around Storyboard but now my head is swimming and I’m a bit exasperated. Storyboard is the only thing standing between me and a finished game!

Does anyone have any tips for a good sample game that shows Storyboard well implemented? The sample that ships with the SDK isn’t robust enough for me.
[import]uid: 105707 topic_id: 28556 reply_id: 118563[/import]

It’s not so much the destroyScene event, the the storyboard.removeScene() API call. I’m not sure the order, but that call will cause a destroyScene event to be generated (calling your destroyScene function) and then all display objects are removed for you.

I have rarely if never put anything in my destroyScene functions.

Things like timers, music cancelling, runtime event listeners, native objects that need removed manually because they cannot be put into groups are typically removed during exitScene()

[import]uid: 19626 topic_id: 28556 reply_id: 118564[/import]

I’m glad to hear that I’m on the right path by doing the “heavy lifting” in my exitScene event.

A great learning experience that I’ve had tonight was figuring out that I need to not just pause my physics in that event but actually stop the physics. That was one part of an apparently complex problem that was plaguing me.

The biggest breakthrough I’ve had tontight relates to how I had set up the function I was using to generate the display objects of my tile based map. I’m not sure why this is but by resetting my table to an empty table prior to generating a new map I now prevent the previous scene from deleting the new scene’s map. Sorry that’s not really intelligible I guess but I’m hugely relieved to say the least.

For the time being, Storyboard seems to be working as I would expect… fingers crossed/knock wood!

Thanks for your help Rob [import]uid: 105707 topic_id: 28556 reply_id: 118571[/import]