什么是更新物理帧速率的正确方法?

我在互联网上search,最终阅读了一篇建议文章, “修复你的Timestep!” 。 按照这篇文章,我提出了一个更新的方法,但是我仍然有问题。 每当我实例化更多的对象,在我的场景中,我的物理交互速度要慢得多。 我已经修复了其他子系统,他们在更新过程中浪费了周期,而且我已经跟踪了我的物理性能下降到这一点。 我认为我更新物理的方式是不对的,因为我为我的Box2D引擎使用了1.0 / 60.0的固定时间。

我在更新过程中犯的错误是什么? 什么是更新物理帧速率的正确方法? 这是我的代码:

 void Core::Update() { // Input this->cInput->Update(); // Physics this->cPhysics->Update(); // Keep frame rate static const double desiredTime = 1.0 / 60.0; static double currentTime = (double)(GetTickCount()); static double accumulator = 0.0; double newTime = (double)(GetTickCount()); double frameTime = newTime - currentTime; if(frameTime > 0.25){ frameTime = 0.25; } currentTime = newTime; accumulator += frameTime; while(accumulator >= desiredTime) { // Input this->cInput->Update(); // Physics this->cPhysics->Update(desiredTime); // Scripts this->cScripts->Update(); accumulator -= desiredTime; } 

我读过,你不应该将你的物理帧率绑定到渲染帧速率,所以我使用this->cPhysics->Update(); 。 我已经使用了我以前的方法,但略有改变; 我不知道我在做什么是对的,但它解决了我的性能问题。 首先,我改变了currentTime ,以毫秒为单位,而不是秒。 最后,我把所有的更新代码移到了一个时间循环中,除了渲染器更新。 我仍然不知道这是否是正确的方法。

问题在这里

  static double currentTime = (double)time(NULL); static double accumulator = 0.0; double newTime = (double)time(NULL); 

你的currentTime和newTime都是这样的,这是行不通的。

你需要测量一帧(最后一帧)所需的时间,并且rest剩下的时间,直到你达到1.0秒/ 60秒。 不要忘记,睡眠不会完全消耗你通过的时间,所以你需要为此而竞争。

获取帧的使用时间的可选方法是对所有帧时间使用滑动窗口方法,并且对时间进行求和并除以计数。

另一个重要的function是限制你实际测量的时间差(比如0.2秒)以避免不稳定性。

编辑1示例代码来说明它

 private double Time = 0.0; private double deltaTArray[10]; private unsigned int deltaTArrayI; // NOTE< this->currentTime must be set once before this is called > void Core::Update() { // Input this->cInput->Update(); double newTime = (double)time(NULL); double deltaT = newTime - this->currentTime; this->currentTime = newTime; deltaT = min(deltaT, 0.25); // because of stability this->deltaTArray[this->deltaTArrayI] = deltaT; (this->deltaTArrayI)++; this->deltaTArrayI = this->deltaTArrayI % 10; // calculate delta T as average of the sliding window double deltaTAverage = 0.0; for( unsigned int i = 0; i < 10; ++i ) { deltaTAverage += this->deltaTArray[i]; } deltaTAverage = deltaTAverage / (double)10; // Physics this->cPhysics->Update(deltaTAverage); // Keep frame rate sleep(max((1.0/60.0)-deltaTAverage, 0)); // Render this->cRender->Update(); }