State was changed after rootNode.updateGeometricState() call

Hi

I’ve been using JME3 for 2-3 months now and I’m still learning. I’m making a 3D game which is sort of streetfighter/tekken like. I’m using GameAppState class to do all the work and this is where the problem is.

I have in total 3 classes. A StartScreen class (nifty), a Main class and a GameStateApp class. The Main class only starts and init’s the startscreen class which then does some basic stuff and starts the GameAppState class after the usere clicks start. Everything in the GameAppState class works fine until I try to exit the game (due to user hits exit or game ends), reset the game or go to next round. The GameAppState as a node called appGameNode. Everything in this class is attached to it and in return it is attached to the rootNode.

I’ve tried to debug this error every now and then for some weeks now and usually I give up, postpone it and work on something else, but I can’t postpone this any longer. I’m getting bald soon :confused:

After some debugging I’ve found that it has something to do with the two things.

  1. Camera
  2. GuiNode

If I comment out my camera method leaving the guiNode as it is, I get the same error except that the Spatial name is “Gui Node” instead of “gameAppNode”

If I comment out both of them, I can exit the game and go to my startscreen without any errors, but my gameAppState is still working even though I’ve detached it from the rootNode

I’ve tried to use app.enqueue as some suggested to in another thread but is didn’t help. I’ve tried to use setEnabled, detach gameAppNode or a combination of both without any success. So yea, I’m getting pretty frustrated now and I’m thinking that I should never again use app states even though “they are very easy and good to use”

The error I’m getting:
Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.IllegalStateException: Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!
Problem spatial name: gameAppNode
at com.jme3.scene.Spatial.checkCulling(Spatial.java:260)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:647)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.water.WaterFilter.preFrame(WaterFilter.java:200)
at com.jme3.post.FilterPostProcessor.preFrame(FilterPostProcessor.java:330)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:957)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:722)

[java]
//Methods in GameAppState class:
//My setEnabled method:
@Override
public void setEnabled(boolean enabled)
{
super.setEnabled(enabled);
if (enabled)
{
enableControls(ninjaNode, true);
rootNode.attachChild(gameNode);
}
else
{
disableInput();
enableControls(ninjaNode, false);
rootNode.detachChild(gameNode);
}
}

//guiNode:
private void addGui()
{

    //guiNode.detachAllChildren();
    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
    
    guiGameTime = new BitmapText(guiFont, false);
    guiGameTime.setSize(0.025f*settings.getWidth() );
    guiGameTime.setLocalTranslation(settings.getWidth()/2 + 0.08f*settings.getWidth(), 1.21f*settings.getHeight(), 0);
    guiGameTime.setColor(ColorRGBA.White);
    
    guiPause = new BitmapText(guiFont, false);
    guiPause.setText("Game is paused. Press \"P\" to unpause.");
    guiPause.setColor(ColorRGBA.Red);
    guiNode.attachChild(guiGameTime);
    gameNode.attachChild(guiNode);
    
}

//Cam Method
private void camZoom()
{
//init camera control node
camControlNode = new Node(“camControlNode”);
camControlNode.setLocalTranslation(camNodePosX, 3.5f, 9);

    Mesh mesh = new Box(0.02f, 0.02f, 0.02f);
    Geometry geo = new Geometry("testBox", mesh);
    geo.setLocalTranslation(camNodePosX, 3.5f, 9f);
    Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    m.setColor("Color", ColorRGBA.Blue);
    geo.setMaterial(m);
    
    camControlNode.attachChild(geo);
    
    // Camera Node
    camNode = new CameraNode("CamNode", cam);
    camNode.setControlDir(CameraControl.ControlDirection.SpatialToCamera);     
    camNode.setLocalTranslation(0, 3.5f, 11f);
    camNode.lookAt(camControlNode.getLocalTranslation(), Vector3f.UNIT_Y);
    camControlNode.attachChild(camNode);
    gameNode.attachChild(camControlNode);
}

private void initCam()
{
flyCam.setMoveSpeed(25);
cam.setLocation(new Vector3f(0, 7, 18));
cam.lookAt(new Vector3f(0, 3, 0), Vector3f.UNIT_Y);
cam.setFrustumFar(500f);
}

//start method in my StartScreen class:
public void startGame(String nextScreen)
{
nifty.gotoScreen(nextScreen); // switch to
stateManager.attach(gameAppState);
stateManager.getState(GameAppState.class).setEnabled(true);

}

[/java]

Thanks a lot.

So no one knows the problem here??
It’s kind of urgent for me atm :frowning:

I found one of the errors. In addGui() I attach the guiNode to the rootNode or in this case gameNode which I shouldn’t!

Anyone got any clues for the other two problems? I’m 80% sure it has something to do with cam since I’m using it in camZoom too!

So many things could be happening:
-either you are modifying the scene graph from another thread
-you are updating the node of some viewport after its update has been called
-you are updating some other node (somehow) after the update has been called.

You can check the first by dropping some System.out.println( Thread.currentThread() ) around in various places to see what’s getting called from where.

…in a normal setup this stuff shouldn’t happen so it’s hard to tell from here what’s different about yours. Seems like something is happening in the code we can’t see. For example, what is gameAppNode and how is it being managed?

gameAppNode is the name of my gameNode which everything in my GameAppState class is hooked too. gameNode is hooked to rootNode. So it is easier for me to detach everything from the root when I leave the GameAppState class (go to another screen). I have tried both setEnabled() to enable/disable everything and attach/detach everything from rootNode, but I still get the error

Regards,
Delly

Somewhere, you are modifying the scene graph from somewhere that isn’t an app state’s update() and isn’t a control’s update and isn’t in simpleUpdate(). We can’t see where, though.