1

我在我的游戏中有一个设置,其中物理在一个单独的线程中更新,实现如下

物理处理器(物理线程)

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 引起的。

有没有人对我可以做些什么来防止这种异常或如何解决它有任何建议?

4

1 回答 1

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一个线程之前执行,所以不用担心线程。

于 2014-05-06T22:06:17.950 回答