我在一个线程中调用world.step(timeStep, iterations, iterations)
,在Screen.render()
中调用另一个线程,这个:
MyBox2DDebugRenderer.render(world, cam.combined);
过了一段时间,我会得到
FATAL EXCEPTION: GLThread 2328
java.lang.IndexOutOfBoundsException: Invalid index 7, size is 7
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at com.kingx.spacejourney.MyBox2DDebugRenderer.renderBodies(MyBox2DDebugRenderer.java:132)
at com.kingx.spacejourney.MyBox2DDebugRenderer.render(MyBox2DDebugRenderer.java:74)
at com.kingx.spacejourney.Universe.render(Universe.java:85)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:449)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
MyBox2DDebugRenderer.java
130 int len = world.getContactList().size();
131 for (int i = 0; i < len; i++)
132 drawContact(world.getContactList().get(i));
因此,在渲染时,box2d世界正在发生变化。你有一些想法如何同步这个?我应该把它放在一个线程中吗?
答案 0 :(得分:0)
正如你所说,box2d世界在渲染时正在改变,这就产生了这个线程问题。
您可以使用Java synchronized
原语来确保一次只有一个线程能够访问box2d资源,即:
第一个帖子(游戏更新):
synchronized(world){
...
// Make the physics work by stepping into time
world.step(1 / 50.0f, BOX_VELOCITY_ITERATIONS, BOX_POSITION_ITERATIONS);
...
}
第二个线程(渲染):
synchronized(world){
...
// Your rendering
MyBox2DDebugRenderer.render(world, cam.combined);
...
}
此处使用world
不是唯一选项,如果两个线程在同一个类中共存,您也可以使用对this
的引用。
关于将所有内容放在一个线程中的选项,它肯定会解决您的问题。但是,在我看来,在两个线程中分离渲染和更新是个好主意。首先,您将更好地使用CPU资源(可能在并行运行多个线程,也可以在移动平台中运行)。其次,如果游戏更新和渲染的速度分开,你的游戏将更容易扩展。
此致