Problem with sceneGroup - Question

I have this code in a touch listener:

                t.pathdots[#t.pathdots+1]=display.newCircle(0,0,4)                 t.pathdots[#t.pathdots].x=event.x                 t.pathdots[#t.pathdots].y=event.y                 sceneGroup:insert(t.pathdots[#t.pathdots])

this is creating some circles along a path and everything is working fine BUT

after reloading this scene (composer) I get the following error:

… : attempt to call method ‘insert’ (a nil value) (for the line sceneGroup:insert(t.pathdots[#t.pathdots]) )

Any ideas what can cause this? the sceneGroup is created in each composer function like this:

local sceneGroup = self.view

Can you discuss how you’re managing the scene? Are you removing it before going to it? Are you creating these objects in scene:create(), scene:show() or elsewhere. When you re-enter the scene, does t.pathdots exist? When do you define it as an empty table?

Rob

Thanks for your fast feedback Rob.

The scene management is as followed:

the sceneGroup is created in each composer function of the scene. The listener is located inside the scene:show() will part. But the listener is added to a button inside the scene did part.

The scene should be removed because I added another empty scene between calling the same scene again.

I have to look into the objects itself now BUT I tried this inside the listener without using the t.pathdots:

local circle=display.newCircle (0,0,6) circle.x=event.x circle.y=event.y sceneGroup:insert(circle) circle=nil

and it has the same result:

Everything works fine in the first call of the scene. Retrying the scene (call it again directly) then brings the error when the button is touched.

… : attempt to call method ‘insert’ (a nil value)

Maybe this info can “circle” the problem some more?

I will do some more tests to find it.

UPDATE:

I am using a module I am loading inside the composer level scene:

local robo = require (“robobase”)

I found a function like this inside this module:

local openroboselectionmenu=function(sceneGroup,pausefunc,robosheet,spawntimerforrobot)    ... end

As you can see in this function I get the sceneGroup from the composer level scene where I call this function.

Inside the function (in the module) I am using sceneGroup, so I can insert new objects which are also created inside this function in the module.

I now have included the following line when changing scenes:

composer.removeScene( “robobase” )

This seems to fix the problem!

Before I only have used this line: composer.removeScene( “level” ) for removing the composer scene where I call the module “robobase” in. But it seems this alone was not enough.

Could this be really the problem here?

We don’t know anything about robobase.lua. While scenes are modules, you should not be requiring a scene, you should be doing a composer.gotoScene(). If your module is not a scene, you should not be calling composer.removeScene() on it.

But if that’s working, it’s because composer.removeScene() will “unrequire” the module. That way, the next time robobase.lua is required, the code in its main chunk will re-run. Already loaded modules will not re-execute code in the main chunk.

The proper way to unrequire a non-scene module would be something like:

robobase = nil package.loaded["robobase"] = nil

when you are done with it. 

I would put that code inside of:  function scene:destroy()

that way, when you removeScene() on your level, your module that needs re-loaded properly will get un-required. Then when you go back to your level scene, robobase will reload from scratch.

Rob

1 Like

Thank you for this explanation. This helps a lot!

Can you discuss how you’re managing the scene? Are you removing it before going to it? Are you creating these objects in scene:create(), scene:show() or elsewhere. When you re-enter the scene, does t.pathdots exist? When do you define it as an empty table?

Rob

Thanks for your fast feedback Rob.

The scene management is as followed:

the sceneGroup is created in each composer function of the scene. The listener is located inside the scene:show() will part. But the listener is added to a button inside the scene did part.

The scene should be removed because I added another empty scene between calling the same scene again.

I have to look into the objects itself now BUT I tried this inside the listener without using the t.pathdots:

local circle=display.newCircle (0,0,6) circle.x=event.x circle.y=event.y sceneGroup:insert(circle) circle=nil

and it has the same result:

Everything works fine in the first call of the scene. Retrying the scene (call it again directly) then brings the error when the button is touched.

… : attempt to call method ‘insert’ (a nil value)

Maybe this info can “circle” the problem some more?

I will do some more tests to find it.

UPDATE:

I am using a module I am loading inside the composer level scene:

local robo = require (“robobase”)

I found a function like this inside this module:

local openroboselectionmenu=function(sceneGroup,pausefunc,robosheet,spawntimerforrobot)    ... end

As you can see in this function I get the sceneGroup from the composer level scene where I call this function.

Inside the function (in the module) I am using sceneGroup, so I can insert new objects which are also created inside this function in the module.

I now have included the following line when changing scenes:

composer.removeScene( “robobase” )

This seems to fix the problem!

Before I only have used this line: composer.removeScene( “level” ) for removing the composer scene where I call the module “robobase” in. But it seems this alone was not enough.

Could this be really the problem here?

We don’t know anything about robobase.lua. While scenes are modules, you should not be requiring a scene, you should be doing a composer.gotoScene(). If your module is not a scene, you should not be calling composer.removeScene() on it.

But if that’s working, it’s because composer.removeScene() will “unrequire” the module. That way, the next time robobase.lua is required, the code in its main chunk will re-run. Already loaded modules will not re-execute code in the main chunk.

The proper way to unrequire a non-scene module would be something like:

robobase = nil package.loaded["robobase"] = nil

when you are done with it. 

I would put that code inside of:  function scene:destroy()

that way, when you removeScene() on your level, your module that needs re-loaded properly will get un-required. Then when you go back to your level scene, robobase will reload from scratch.

Rob

Thank you for this explanation. This helps a lot!