Why doesn't composer.gotoScene() allow transitions when reloading the same scene?

I would really like to be able to use transition effects when reloading the same scene using composer.

Found this archived topic about this issue: https://forums.coronalabs.com/topic/60615-reload-scene-with-effects-is-not-working/

However, I don’t think that the accepted answer really explains why composer doesn’t allow transitions when reloading the same scene more than stating that it’s “by design”.

I’m using overlays to present pause menu, game over dialog etcetera, which means I don’t always have an intermediate scene that I can transition to/from. For example I want to be able to use a transition effect when pressing a “Retry” button in on of my overlay menus.

Any chance this will be implemented? 

The reason, specifically, is because composer scenes are essentially tied to a single module (Lua file) which means they are bound by the same loading behaviour as Lua modules are - that is: once a module is loaded, calling ‘require’ to load it again simply returns the same object as calling it the first time. You need to deliberately tell Corona to remove it if you want it to be loaded again.

Yes, it is a bit irritating when you want to use a single scene module and have it dynamically load your level data, etc.

Please, take the learning from others here and just accept that, at least in the Lua world, this is more of a beneficial side effect that a negative - in general.

To achieve, at least, the effect of one scene reloading there are a number of things you can do…

Create a function which returns a display group which can behave in the way you want your games conceptual scene to behave (fading in/out, etc) and use that within your composer scene. Rather than using gotoScene to leave the scene, simply create a new game level object and transition it on while the old one is transitioned away. This is good code reuse and gives you great control. (I made the beneficial statement above because, as you code this solution up, you’ll see that there are many clever things you’ll want to do which composer scenes are also not the right solution for - such as complex effects or anything which is specific to your app and not generic.)

You can take the easy route and simply goto another ‘intermediate’ scene, unload the game level scene and then goto the game level scene again. This will cause it to reload. It doesn’t help if you want them both on the screen at the same time.

You could also goto an intermediate scene and then goto the game level scene again, but pass it a parameter which causes it to load a different game level during the ‘show’ ‘began’ phase. This might suffer from stutter if you have a lot of loading to do.

There are probably lots of other solutions, but these are the ones I tend to go for. (I’m not a wizard.)

if you want to know the “why” then grab a copy of the legacy storyboard source.

composer is essentially just “storyboard 2.0” rebranded, so very high probability that composer does it the exact same way.

follow gotoScene’s logic through to reloadScene, then look at the hacky mess of timer.performWithDelay’s that actually accomplish it.  those timers won’t work if they also had to wait for transitions in between them.  (at least, not without adding a lot MORE hacky mess!)

the workaround:  create an intermediate “Retry” scene that will automatically transition to the next scene after a very short delay.  (ie timer.performWithDelay or an enterFrame counter, etc)  works well for fade-to-black/etc, won’t work so well for slides/etc.

Transitioning between scenes takes two scenes. One to transition from and one to transition to. If you attempt to reload the current scene it’s going to transition to itself. We have always encouraged people to use a cutscene if you want to freshly restart a scene.  Composer and it’s older brother Storyboard are based on one managed display group per scene.  Restarting a scene without using a cutscene where you can remove the old scene and start fresh, requires you reset all your objects to their initial position, rotation, momentum (if you’re using physics), alpha etc. Any variables like scores, lives, etc. have to also be reset. The cutscene method is simply the easiest way.

Rob

Thanks for the responses guys! I’ve worked around this so far by implementing a manual fade in/out transition using a display object that covers the entire screen of the scene being reloaded. Think I’ll stick to that solution for now and will switch to using an intermediate scene if necessary. 

I wrote a little blog post on this topic which can be read here if interested: http://bitstopixels.blogspot.com/2018/06/corona-reloading-scene-with-transition.html

The blog post also includes Lua source code for a reusable and customizable transition scene.

Another option could be to take a screenshot immediately before transitioning to a dummy scene, this scene just displays the screenshot and then transitions back to the original scene.

I’d go with the screenshot approach personally.

You could always have a layer above composer to “cover your scene reloading”?

Or flush the screen and force it to completely reinstall maybe?

Yes, a screenshot is another option, should have brought that up as well. The problem with that approach is that any ongoing animations will appear to freeze, and that doesn’t look very good if you want a somewhat slow scene transition. In my case, I wanted things like background snow etcetera to continue animating while fading/moving out the scene.

EDIT: Lol, after writing this I noticed that I actually do stop the animations anyway when I start the scene transition, at least in the gifs shown in the blog post. Consider that a bug that will be fixed.  :lol:  

The reason, specifically, is because composer scenes are essentially tied to a single module (Lua file) which means they are bound by the same loading behaviour as Lua modules are - that is: once a module is loaded, calling ‘require’ to load it again simply returns the same object as calling it the first time. You need to deliberately tell Corona to remove it if you want it to be loaded again.

Yes, it is a bit irritating when you want to use a single scene module and have it dynamically load your level data, etc.

Please, take the learning from others here and just accept that, at least in the Lua world, this is more of a beneficial side effect that a negative - in general.

To achieve, at least, the effect of one scene reloading there are a number of things you can do…

Create a function which returns a display group which can behave in the way you want your games conceptual scene to behave (fading in/out, etc) and use that within your composer scene. Rather than using gotoScene to leave the scene, simply create a new game level object and transition it on while the old one is transitioned away. This is good code reuse and gives you great control. (I made the beneficial statement above because, as you code this solution up, you’ll see that there are many clever things you’ll want to do which composer scenes are also not the right solution for - such as complex effects or anything which is specific to your app and not generic.)

You can take the easy route and simply goto another ‘intermediate’ scene, unload the game level scene and then goto the game level scene again. This will cause it to reload. It doesn’t help if you want them both on the screen at the same time.

You could also goto an intermediate scene and then goto the game level scene again, but pass it a parameter which causes it to load a different game level during the ‘show’ ‘began’ phase. This might suffer from stutter if you have a lot of loading to do.

There are probably lots of other solutions, but these are the ones I tend to go for. (I’m not a wizard.)

if you want to know the “why” then grab a copy of the legacy storyboard source.

composer is essentially just “storyboard 2.0” rebranded, so very high probability that composer does it the exact same way.

follow gotoScene’s logic through to reloadScene, then look at the hacky mess of timer.performWithDelay’s that actually accomplish it.  those timers won’t work if they also had to wait for transitions in between them.  (at least, not without adding a lot MORE hacky mess!)

the workaround:  create an intermediate “Retry” scene that will automatically transition to the next scene after a very short delay.  (ie timer.performWithDelay or an enterFrame counter, etc)  works well for fade-to-black/etc, won’t work so well for slides/etc.

Transitioning between scenes takes two scenes. One to transition from and one to transition to. If you attempt to reload the current scene it’s going to transition to itself. We have always encouraged people to use a cutscene if you want to freshly restart a scene.  Composer and it’s older brother Storyboard are based on one managed display group per scene.  Restarting a scene without using a cutscene where you can remove the old scene and start fresh, requires you reset all your objects to their initial position, rotation, momentum (if you’re using physics), alpha etc. Any variables like scores, lives, etc. have to also be reset. The cutscene method is simply the easiest way.

Rob

Thanks for the responses guys! I’ve worked around this so far by implementing a manual fade in/out transition using a display object that covers the entire screen of the scene being reloaded. Think I’ll stick to that solution for now and will switch to using an intermediate scene if necessary. 

I wrote a little blog post on this topic which can be read here if interested: http://bitstopixels.blogspot.com/2018/06/corona-reloading-scene-with-transition.html

The blog post also includes Lua source code for a reusable and customizable transition scene.

Another option could be to take a screenshot immediately before transitioning to a dummy scene, this scene just displays the screenshot and then transitions back to the original scene.

I’d go with the screenshot approach personally.

You could always have a layer above composer to “cover your scene reloading”?

Or flush the screen and force it to completely reinstall maybe?

Yes, a screenshot is another option, should have brought that up as well. The problem with that approach is that any ongoing animations will appear to freeze, and that doesn’t look very good if you want a somewhat slow scene transition. In my case, I wanted things like background snow etcetera to continue animating while fading/moving out the scene.

EDIT: Lol, after writing this I noticed that I actually do stop the animations anyway when I start the scene transition, at least in the gifs shown in the blog post. Consider that a bug that will be fixed.  :lol: