我在我的游戏中有一个设置,其中物理在一个单独的线程中更新,其实现如下
物理处理器(物理线程)
public class PhysicsProcessor extends Runnable {
private DynamicsWorld world;
public PhysicsProcessor() {
/* basic dynamics world setup with dvbt broadphase :P */
}
public synchronized getDynamicsWorld() { return world; }
@Override
public void run() {
/* update time */
//update phyics
getDynamicsWorld().stepSimulation(/* delta time */);
}
}
主线程中的对象创建示例
myPhysicsProcessor.getDynamicsWorld.addRigidBody(/* some rigid body created here */);
问题在于,当游戏运行时,偶尔会在“stepSimulation”的单独线程中获得空指针异常,这是由我的dbvt broadphase中的setAabb引起的。
是否有人对我可以采取哪些措施来防止此异常或如何解决此问题?
答案 0 :(得分:0)
你可以从它的外观中创造世界final
。然后,这将显示同步访问的无用性:
public class PhysicsProcessor extends Runnable {
private final DynamicsWorld world;
public synchronized DynamicsWorld getDynamicsWorld() { return world; } //why sync? it can't change
}
您会看到:myPhysicsProcessor.getDynamicsWorld().addRigidBody(...)
同步在getDynamicsWorld()
返回后停止。因此addRigidBody(...)
在安全同步上下文之外调用。
不,您要做的是确保始终在 同步块中使用
@Override
public void run() {
//update physics
synchronized(this) {
world.stepSimulation(/* delta time */);
}
}
public void addBody(/*args here*/) {
synchronized(this) {
world.addRigidBody(/*args here*/);
}
}
现在一个方法没问题,但如果你发现自己想要以这种方式在跑步者之外做很多DynamicsWorld
的方法,或者只是想要另一个选择,那么这个方法不需要同步:
public interface IWorldRunable {
void run(DynamicsWorld world);
}
public class PhysicsProcessor extends Runnable {
private final DynamicsWorld world;
private final ConcurrentLinkedQueue<IWorldRunable> worldRunables = ConcurrentLinkedQueue<IWorldRunable>();
public PhysicsProcessor() {
/* basic dynamics world setup with dvbt broadphase :P */
}
@Override
public void run() {
/* update time */
//run runables on world
for(IWorldRunable runable : worldRunables)
runable.run(world);
//clear runables
worldRunables.clear();
//update phyics
world.stepSimulation(/* delta time */);
}
public void do(IWorldRunable runnable) {
worldRunables.add(runnable);
}
}
然后你会这样做,添加一个正文:
myPhysicsProcessor.do(new IWorldRunable(){
@Override
public void run(DynamicsWorld world){
world.addRigidBody(...);
}
});
它会在同一个线程上的下一个stepSimulation
之前执行,所以没有线程担心。