Periodic actions

Heya, I want to update my nodes every 2 seconds, atm I have something like this in simpleUpdate:

[java]

sum += tpf;



if(sum >= 2.0) {

//update stuff

sum = 0.0;

}

[/java]



is this the correct way of doing it or is there some other best practice way e.g. with events.

have a seperate thread do the updating… Then the main thread runs more consistent because you don’t have a big bunch of nodes which are updated every so often in the main thread which causes a delay.

I guess you should not update notes (scene graph) from other threads … you can use threads to “prepare” internal objects etc. I read this in some post here in the forum …

True, updating from multiple threads can cause all kinds of troubles with locking etc. You could circumvent that by using synchronized blocks or something like that, but that’s also not a good idea performanse wise.



Having a seperate thread set a boolean might be your best bet in the end. Since checking a boolean is a lot faster then checking and updating an int.

Thanks for the answers, I tried with the threads (TimerTask with Timer) but I get this error:



java.lang.IllegalStateException: Scene graph is not properly updated for rendering.

Make sure scene graph state was not changed after

rootNode.updateGeometricState() call.

Problem spatial name: Root Node

at com.jme3.scene.Spatial.checkCulling(Spatial.java:229)

at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:508)

at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:712)

at com.jme3.renderer.RenderManager.render(RenderManager.java:742)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:249)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:158)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:203)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:221)

at java.lang.Thread.run(Thread.java:636)



so its not exactly something I can synchronize.

Depending on the nature of you rupdate you might be able to do it incrementally . So every update a little, however if it is not splitable and needs acces to the scene graph there is no solution that does not lead to microlags then.

You cant just spawn another thread and do stuff on that, do threading like this in jME:

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:multithreading

You should use a control or an appstate.

Never update your scene graph from another thread.

Callables? Let other thread determine what they need to and then use enqueue through a callable. Set up a few common routines… such as:

[java]

private void transSceneNode(Node node, Vector3f v) {

class transNode implements Callable {

Node node;

Vector3f v;

public transNode(Node node, Vector3f v) {

this.node = node;

this.v = v;

}

public Object call() {

node.setLocalTranslation(v);

return null;

}

}

transNode task = new transNode(node, v);

enqueue(task);

}

[/java]

1 Like

Anonymous inner classes ftw!! :smiley:

While anonymous inner classes can be handy from tim to time, this piece of code somehow makes my skin crawl. :frowning:

While anonymous inner classes can be handy from tim to time, this piece of code somehow makes my skin crawl. :frowning:

While anonymous inner classes can be handy from tim to time, this piece of code somehow makes my skin crawl. :frowning:

Hmm… I guess threading isn’t going to work for me then because I constantly change the scene graph but you guys gave me lots of stuff to rack my brains on for future projects (if I ever get around to them :P).



Just out of curiosity is it ok to enqueue tasks in another thread? An RPG with spell effects comes to mind like a spell that halves your strength for 10 seconds. Would you be able to create a task that enqueues the reversing effect in the application like so:

[java]

Callable<Integer> reverseStrengthEffect = new Callable<Boolean>() {

public Integer call() throws Exception {

player.setStrength(player.getStrength() * 2);

return player.getStrength();

}

}



Timer t = new Timer();

TimerTask task = new TimerTask() {

public void run() {

enqueue(reverseStrengthEffect);

}

}



//and then as soon as the player gets hit by the spell

t.schedule(task, 10000); //enqueue after 10s

[/java]



Will reverseStrengthEffect be called in the new task thread or in the rendering thread?

Yes, read the wiki document I linked, it describes exactly how you should do it.

normen said:
Yes, read the wiki document I linked, it describes exactly how you should do it.


I did read it, I just didn't understand how to enqueue a task to be run at some specified point in the future. In the snippet I posted TimerTask is a runnable so I wasn't sure if the enqueue schedules the Callable to be run in the render thread or in the TimerTask thread. I found that ScheduledThreadPoolExecutor has a schedule method so that can be used instead of submit. I understand now thanks.