@dan56 filled out a documentation request on this, and I thought I should share my response here:
Generally speaking, you should not remove the scene that’s currently on the screen. After some testing, we found it’s safe to remove the current scene in the scene:hide()'s “did” phase. This is what the Getting Started guide says. The Getting Started guide is meant to not overwhelm the new developer with more obscure use cases. It’s likely safer to drop the composer.removeScene() inside a short timer to make sure all other things like pausing physics, timers being removed etc. actually happen before you remove the scene. In the case of the game you’re building, it should be safe to do it without a timer, but other users may find a timer to be more practical:
function scene:hide( event ) if ( event.phase == "did" ) then timer.performWithDelay( 100, function() composer.removeScene( "game" ); end ) end end
assuming of course that your scene is named “game”. A 1-second timer will execute in the next frame which is either 1/30th of a second or 1/60th of a second later, not really in 1 millisecond. If your frame rate is 60 fps, the next frame will happen in 17 milliseconds, so any
time between 1 and 17 will be the same frame. It’s also not going to hurt to wait even longer. Your user isn’t going to react in a 10th of a
second to go back to your scene.
Now for some additional commentary…
Now, all that said, I am not a fan of removing scenes even in scene:hide() anyway. There is no harm leaving a scene in memory, unless you need to free the memory. It’s more work, but the **right way** to reset a scene and be more computer efficient is to reset objects during scene:show()'s “will” phase. Move your objects back to their starting position, reset rotations, set physics starting values, etc. If you want to take advantage of scene caching, this is what you should do. Yes, it’s more work on you. It takes planning and effort to get ti right.
Programmers are always looking for efficiency. That, of course, could be more efficient ways to do things like faster sorting methods, but frequently it’s ways to write less code. Removing a scene is a brute force way of resetting a scene, but it’s just that a brute force method. Yes, you write one line of code vs. potentially dozens or hundreds, but you’re causing the system to have to recreate things, reload images from storage, etc. While one developer might call it programmer efficiency, others could call it a lazy hack.
It’s one I’m quite guilty of in my own apps and games. I will remove the scene to reset it. However, I almost never reset it in the scene:hide() “did” phase. Instead, I remove the scene before I go to it. It’s pretty easy to do:
composer.removeScene("game") composer.gotoScene("game")
You’re not messing with timers. You’re not messing if the scene is still on the screen or not. You’re not messing with deleting yourself.
And if you’re thinking about saving lines of code, it doesn’t really save that much. If you’re already doing:
local player = display.newImageRect(“player.png”, 100, 1000)
sceneGroup:insert(player)
player.x = 50
player.y = display.contentCenterY
physics.addBody( player, …)
player:addEventListener( “touch”, playerTouchHandler )
in scene:create(), it’s not that much more work to:
local player -- at the top of the module outside of any functions for scope
in scene:create()
player = display.newImageRect("player.png", 100, 1000) sceneGroup:insert(player)
in scene:show()
if event.phase == "will" then player.x = 50 player.y = display.contentCenterY physics.addBody( player, ...) player:addEventListener( "touch", playerTouchHandler )end
That’s one more line of code. But you would want to remove the physics body in scene:hide()'s “did” phase. You may need to set the initial rotation, and physics properties too, which is where the extra code comes into play.
Rob