Войти
ПрограммированиеФорумФизика

"Заикание" физики

#0
5:33, 18 янв. 2021

В данный момент использую такой код для вызова обновления физики в главном цикле:

While (!quit) {    
    currentTime = std::chrono::high_resolution_clock::now();
    float deltaTime = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
    if (deltaTime > prevUpdateTime + dt)
    {
      prevUpdateTime += dt;
      updatePhysics(dt);
    }
// Рендер
}

Это хорошо работает на мощных машинах. Но если фпс просаживается даже на самую малость, то получается "заикание" - изображение как бы на малую долю секунды "замирает". Как усовершенствовать вызов обновления физики чтобы такого не было?


#1
(Правка: 9:21) 9:16, 18 янв. 2021

Замени это:

    if (deltaTime > prevUpdateTime + dt)
    {
      prevUpdateTime += dt;
      updatePhysics(dt);
    }
на это:
    while (prevUpdateTime < currentTime)
    {
      prevUpdateTime += dt;
      updatePhysics(dt);
    }
А deltaTime вообще неясно зачем нужна.

#2
9:21, 18 янв. 2021

Mikle
> Замени это:
Не повлияло.
Нагуглил, что в этом случае поможет только интерполяция между предыдущим и текущим состоянием кадра. Пипец, это надо считать и хранить все предыдущие позиции и повороты, и местами не только их.

#3
9:23, 18 янв. 2021

MikeNew
Посмотри последнюю правку. У меня так, и оно нормально работает, специально добавлял сильные тормоза и проверял.

#4
9:49, 18 янв. 2021

Mikle
> while (prevUpdateTime < currentTime)
prevUpdateTime - это флоат
currentTime - это std::chrono::time_point
не получится сравнить.

Набросай пожалуйста псевдокод, как у тебя сделано.

#5
9:58, 18 янв. 2021
Const DTime As Double = 1 / 200
Dim OldTime As Double

  While Running
    Dim t As Double
    t = QTime ' точное текущее время в Double
    While t - OldTime > DTime
      Tick ' расчёт физики
      OldTime = OldTime + DTime
    Wend
    Render
  Wend
#6
10:13, 18 янв. 2021

Самая лучшая физика для игр, это физика умеющая работать в мультиплеерной сетевой игре. Именно в этом направлении вы найдёте все необходимые вам правильные ответы.

#7
(Правка: 4:59) 4:57, 19 янв. 2021

физика должна обновляться кратно рендеру, но, желательно, не слишком во много раз.
Можно даже сделать чтобы программа сама определяла эту кратность для данной машины.

#8
10:30, 19 янв. 2021

аккумулятор сглаживающий сколько реально занял тик где?
а фиксированный шаг физики?

https://gafferongames.com/post/fix_your_timestep/

#9
10:34, 19 янв. 2021

#!
> а фиксированный шаг физики?
В моём варианте так и есть, DTime - константа.

#10
14:00, 19 янв. 2021

Проблема может возникнуть в случае если за несколько кадров рендера накапливается еще один кадр физики. При этом возникает "скачек" - объекты на данном кадре сдвинутся в два раза быстрее. Для пользователя это будет выглядеть, как будто объекты время от времени подергиваются. Другая проблема - если расчет физики достаточно тяжелый и при накоплении дополнительного кадра физики возникает просадка fps.

#11
3:54, 20 янв. 2021

MikeNew
> Нагуглил, что в этом случае поможет только интерполяция между предыдущим и
> текущим состоянием кадра. Пипец, это надо считать и хранить все предыдущие
> позиции и повороты, и местами не только их.
Можно ещё экстраполяцию попробовать — то есть, взять последние положение и скорость объекта, и подвинуть его с учетом неизрасходованного кусочка времени кадра, оставшегося в аккумуляторе.
На глаз может быть практически неотличимо от интерполяции.

Mirrel
Не, физику лучше раз и навсегда приколотить к какой-то заданной частоте. Потому что от неё зависит поведение игры: например, с одной частотой ты можешь куда-то допрыгнуть, а с другой — нет.

#12
(Правка: 13:01) 13:01, 20 янв. 2021

BUzer, да, я уже это понял. Что физику можно раза в два ускорить (максимально), но и этого делать не стоит. Значит должна просто соответствовать частоте кадров.

В противном случае, при больших нагрузках на машине слабже будут проявляться непредвиденные глюки. И вероятно не решаемые.

ПрограммированиеФорумФизика