Когда следует использовать фиксированный или переменный шаг времени?

Если игровой цикл основан на фиксированных или переменных шагах времени? Является ли всегда превосходным, или правильный выбор зависит от игры?

Шаг с переменным шагом

Обновления физики передаются аргументом «время, прошедшее с момента последнего обновления» и, следовательно, зависят от частоты кадров. Это может означать выполнение вычислений как position += distancePerSecond * timeElapsed.

Плюсы : плавный, простой в использовании код
Против : не детерминированный, непредсказуемый на очень малых или больших шагах

пример deWiTTERS :

while( game_is_running ) {
    prev_frame_tick = curr_frame_tick;
    curr_frame_tick = GetTickCount();
    update( curr_frame_tick - prev_frame_tick );
    render();
}

Фиксированный шаг времени

Обновления могут даже не принимать «время, прошедшее», так как они предполагают, что каждое обновление относится к фиксированному периоду времени. Вычисления могут выполняться как position += distancePerUpdate. Пример включает интерполяцию во время рендеринга.

Профи : предсказуемый, детерминированный (проще для сетевой синхронизации?), более четкий код расчета
Против : не синхронизируется с монитором v-sync (вызывает дрожащую графику, если вы не интерполируете), ограничена максимальная частота кадров (если вы не интерполируете), трудно работать в рамках, которые предполагают переменные временные шаги (например, Pyglet или Flixel )

пример deWiTTERS :

while( game_is_running ) {
    while( GetTickCount() > next_game_tick ) {
        update();
        next_game_tick += SKIP_TICKS;
    }
    interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick )
                    / float( SKIP_TICKS );
    render( interpolation );
}

Некоторые ресурсы

249 голосов | спросил Nick Sonneveld 26 J000000Monday10 2010, 15:36:03

11 ответов


126

Есть два вопроса, связанные с вопросом.

  • Должна ли скорость физического шага привязываться к частоте кадров?
  • Если физика будет проходить с постоянными дельтами?

В фильме Глена Филдера «Исправьте физику». Это означает, что скорость обновления физической активности должна быть не привязана к вашей частоте кадров.

  

Например, если частота кадров дисплея   составляет 50 кадров в секунду, а симуляция   предназначен для работы со скоростью 100 кадров в секунду, тогда нам нужно   проводить два этапа физики каждый   отобразить обновление, чтобы сохранить физику в   синхронизации.

В рекомендациях Эрин Кэтто для Box2D он также защищает это.

  

Так что не завязывай   временной шаг к частоте кадров   (если вам действительно не нужно).

Если скорость шага физики привязана к вашей частоте кадров? Нет.


Мысли Эрин о фиксированном шаге против переменного шага:

  

Box2D использует вычислительный алгоритм, называемый интегратором. Интеграторы моделируют физические уравнения в отдельные моменты времени. ... Нам также не нравится, как шаг на шаг сильно изменился. Переменный шаг времени дает переменные результаты, что затрудняет отладку.

Мысли Глена о фиксированном vs переменном шаге:

  

Исправить ваш timestep или explode

     

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

Если физика будет ступенчато с постоянными дельтами? Да.


Путь к физике с постоянными дельтами и не связать скорость обновления физики с частотой кадров по-прежнему заключается в использовании аккумулятора времени. В моей игре я делаю шаг вперед. Я применяю функцию сглаживания к входящему времени. Таким образом, большие всплески FPS не приводят к тому, что физика слишком сильно перескакивает, вместо этого они имитируются быстрее для кадра или двух.

Вы упомянули, что с фиксированной скоростью физика не будет синхронизироваться с дисплеем. Это верно, если целевая физическая скорость приближается к целевой частоте кадров. Хуже частота кадров больше, чем физическая скорость. В общем, лучше настроить таргетинг на физический уровень обновления в два раза по сравнению с вашим целевым FPS, если вы можете себе это позволить.

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

ответил deft_code 26 J000000Monday10 2010, 21:44:40
54

Я думаю, что есть 3 варианта, но вы перечисляете их только как 2:

Вариант 1

Ничего не делай. Попытка обновления и рендеринга с определенным интервалом, например. 60 раз в секунду. Если он отстает, пусть и не волнуется. Игры замедлятся в отрывистое замедленное движение, если процессор не сможет идти в ногу с вашей игрой. Этот вариант не будет работать вообще для многопользовательских игр в режиме реального времени, но подходит для игр с одним игроком и успешно используется во многих играх.

Вариант 2

Используйте время дельта между каждым обновлением, чтобы изменить перемещение объектов. Велика в теории, особенно если ничто в вашей игре не ускоряется или замедляется, а просто движется с постоянной скоростью. На практике многие разработчики плохо это реализуют, и это может привести к непоследовательному обнаружению столкновений и физике. Кажется, некоторые разработчики считают, что этот метод проще, чем есть. Если вы хотите использовать эту опцию, вам необходимо значительно повысить свою игру и выявить некоторые математические алгоритмы и алгоритмы, например, используя интегратор физики Верле (а не стандартный Euler, который используется большинством людей) и используя лучи для обнаружения столкновений а не простые дистанционные проверки Пифагора. Я задал вопрос об этом в Stack Overflow некоторое время назад и получил отличные ответы:

https://stackoverflow.com /вопросы /153507 /высчитывает-The-позиционно-оф-ан-ускоряя-тело-после-а-определенного времени

Вариант 3

Используйте подход Gaffer «исправить свой временной шаг». Обновите игру в фиксированных шагах, как в варианте 1, но делайте это несколько раз для каждого рендеринга кадра - в зависимости от того, сколько времени прошло - так, чтобы игровая логика продолжала работать в режиме реального времени, оставаясь на дискретных шагах. Таким образом, легко реализовать логику игры, такую ​​как интеграторы Euler и простое обнаружение конфликтов. У вас также есть возможность интерполировать графические анимации на основе дельта-времени, но это только для визуальных эффектов, и ничто не влияет на вашу основную логику игры. У вас могут возникнуть проблемы, если ваши обновления будут очень интенсивными - если обновления отстают, вам нужно будет все больше и больше из них, чтобы они не отставали, потенциально делая вашу игру еще менее отзывчивой.

Лично мне нравится вариант 1, когда я могу уйти с ним и вариант 3, когда мне нужно синхронизировать с реальным временем. Я уважаю, что Вариант 2 может быть хорошим вариантом, когда вы знаете, что делаете, но я достаточно хорошо знаю свои ограничения, чтобы оставаться вдали от него.

ответил Iain 27 J000000Tuesday10 2010, 00:22:02
25

Мне очень нравится, как XNA Framework реализует фиксированный шаг времени. Если данный призыв к вызову занимает слишком много времени, он будет вызывать обновление несколько раз, пока он не «догонит». Шон Харгривз описывает это здесь:
http://blogs.msdn.com/b/shawnhar/archive/2007/11/23/game-timing-in-xna-game-studio-2-0.aspx

  

В версии 2.0 поведение Draw изменилось:

     
  • Вызовите обновление столько раз, сколько необходимо, чтобы догнать текущее время
  •   
  • Вызов Draw once
  •   
  • Подождите, пока не придет время для следующего обновления
  •   

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

note: xna также поддерживает переменную timestep, это просто настройка.

ответил Joel Martinez 26 J000000Monday10 2010, 18:25:30
11

Есть еще один вариант - отменить обновление игры и обновление физики. Попытка настроить физический движок на игровой тайм-тест приводит к проблеме, если вы исправите свой временной тайм (проблема выхода из-под контроля, потому что интеграция требует больше времени, для чего требуется больше времени, которое требует больше времени), или сделать его переменным и получить неустойчивую физику.

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

Это не тривиально реализовать, но может доказать, что это будет будущим доказательством.

ответил Kaj 27 J000000Tuesday10 2010, 10:56:52
8

Лично я использую вариацию переменной шага времени (который, как мне кажется, является своего рода гибридом фиксированной и переменной). Я подчеркивал эту систему синхронизации несколькими способами, и я нахожу, что использую ее для многих проектов. Я рекомендую его для всего? Наверное, нет.

Мои игровые циклы вычисляют количество кадров для обновления (назовем это F), а затем выполняем F дискретные логические обновления. Каждое обновление логики предполагает постоянную единицу времени (что часто составляет 1/10 секунды в моих играх). Каждое обновление выполняется в последовательности до тех пор, пока не будут выполнены все F дискретные логические обновления.

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

Плохая реализация этого будет просто выполнять F = текущее время - последние обновления времени кадра. Но если расчеты заходят слишком далеко (иногда из-за не зависящих от вас обстоятельств, таких как другой процесс, крадущий процессорное время), вы быстро увидите ужасное пропущение. Быстро, что стабильная FPS, которую вы пытались сохранить, становится SPF.

В моей игре я допускаю «плавное» (сорт) замедление, чтобы ограничить количество логического дозаправки, которое должно быть возможным между двумя ничьими. Я делаю это путем зажима: F = min (F, MAX_FRAME_DELTA), который обычно имеет MAX_FRAME_DELTA = 2/100 * с или 3/100 * с. Таким образом, вместо того, чтобы пропускать кадры, когда слишком далеко позади игровой логики, отбросьте любую огромную потерю кадра (что замедляет работу), восстановите несколько кадров, нарисуйте и повторите попытку.

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

Псевдокод конечного продукта - это что-то вроде этого (дельта F упоминается ранее):

// Assume timers have 1/100 s resolution
const MAX_FRAME_DELTA = 2
// Calculate frame gap.
var delta = current time - last frame time
// Clamp.
delta = min(delta, MAX_FRAME_RATE)
// Update in discrete steps
for(i = 0; i < delta; i++)
{
    update single step()
}
// Caught up again, draw.
render()

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

ответил Overkill 17 PM000000120000000331 2010, 12:29:03
6

Это решение не относится ко всему, но существует еще один уровень переменной timestep - переменная timestep для каждого объекта в мире.

Это кажется сложным, и это может быть, но думать об этом как о моделировании игры как о дискретном симуляции событий. Каждое движение игрока может быть представлено как событие, которое начинается, когда начинается движение, и заканчивается, когда движение заканчивается. Если есть какое-либо взаимодействие, требующее разделения события (например, столкновение), событие отменяется, а другое событие помещается в очередь событий (что, вероятно, является очередью приоритетов, отсортированной по времени окончания события).

Рендеринг полностью отключен от очереди событий. Механизм отображения интерполирует точки между временем начала /окончания события по мере необходимости и может быть как можно точнее или неаккуратно в этой оценке.

Чтобы увидеть сложную реализацию этой модели, см. космический симулятор EXOFLIGHT . Он использует другую модель исполнения от большинства симуляторов полета - основанную на событиях модель, а не традиционную модель фиксированного времени-среза. Основной основной цикл этого типа моделирования выглядит так: в псевдокоде:

while (game_is_running)
{
   world.draw_to_screen(); 
   world.get_player_input(); 
   world.consume_events_until(current_time + time_step); 
   current_time += time_step; 
}

Основной причиной использования одного в космическом симуляторе является необходимость обеспечения произвольного ускорения по времени без потери точности. Некоторые миссии в EXOFLIGHT могут занять игровые годы, и даже 32-кратное ускорение будет недостаточным. Вам понадобится ускорение более чем 1 000 000 раз для пригодного для использования сима, что трудно сделать в модели временного фрагмента. С помощью модели, основанной на событиях, мы получаем произвольные скорости времени от 1 с до 7 мс до 1 с = 1 год.

Изменение скорости времени не изменяет поведение сима, что является критическим признаком. Если для запуска симулятора с требуемой скоростью недостаточно мощности процессора, события будут складываться, и мы можем ограничить обновление пользовательского интерфейса до тех пор, пока очередь событий не будет очищена. Точно так же мы можем ускорить продвижение sim столько, сколько хотим, и быть уверенным, что мы не тратим процессор и не жертвуем точностью.

Итак, подытожим: мы можем моделировать одно транспортное средство на длинной неторопливой орбите (с использованием интеграции Рунге-Кутта) и другого транспортного средства, одновременно подпрыгивающего вдоль земли - оба автомобиля будут смоделированы с соответствующей точностью, поскольку у нас нет глобальный тайм-аут.

Минусы: сложность и отсутствие каких-либо готовых физических движков, поддерживающих эту модель:)

ответил sehugg 9 Mayam11 2011, 01:22:35
5

Фиксированный шаг времени полезен при учете точности с плавающей запятой и согласовании обновлений.

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

now = currentTime
frameTime = now - lastTimeStamp // time since last render()
while (frameTime > updateTime)
    update(timestep)
    frameTime -= updateTime     // update enough times to catch up
                                // possibly leaving a small remainder
                                // of time for the next frame

lastTimeStamp = now - frameTime // set last timestamp to now but
                                // subtract the remaining frame time
                                // to make sure the game will still
                                // catch up on those remaining few millseconds
render()

Основная проблема с использованием фиксированного шага времени заключается в том, что игроки с быстрым компьютером не смогут использовать скорость. Рендеринг со скоростью 100 кадров в секунду, когда игра обновляется только со скоростью 30 кадров в секунду, такая же, как и рендеринг со скоростью 30 кадров в секунду.

При этом может быть возможно использовать более одного фиксированного шага времени. 60fps можно использовать для обновления тривиальных объектов (таких как пользовательский интерфейс или анимированные спрайты) и 30 кадров в секунду для обновления нетривиальных систем (таких как физика) и даже более медленных таймеров для управления за кулисами, таких как удаление неиспользуемых объектов, ресурсов и т. Д.

ответил Nick Bedford 5 Mayam11 2011, 03:37:13
3

В дополнение к тому, что вы уже сказали, это может привести к ощущению, которое вы хотите иметь в своей игре. Если вы не можете гарантировать, что у вас всегда будет постоянная частота кадров, тогда вы, вероятно, будете замедляться где-то, а фиксированные и переменные шаги времени будут выглядеть совсем по-другому. Исправлено будет действие вашей игры в замедленном движении на некоторое время, что иногда может быть предполагаемым эффектом (посмотрите на старый школьный шутер типа Икаруга, где массовые взрывы вызывают замедление после избиения босса). Переменные временные метки будут держать вещи на правильной скорости с точки зрения времени, но вы можете увидеть внезапные изменения в позиции и т. Д., Что может затруднить выполнение игроком действий.

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

Я всегда склонялся к переменному подходу лично, но в этих статьях есть интересные вещи, о которых нужно подумать. Я все же обнаружил, что фиксированные шаги довольно распространены, особенно на консолях, где люди думают, что частота кадров составляет 60 кадров в секунду по сравнению с очень высокими коэффициентами, достигаемыми на ПК.

ответил identitycrisisuk 26 J000000Monday10 2010, 17:40:12
0

Используйте подход Gaffer «исправить свой временной шаг». Обновите игру в фиксированных шагах, как в варианте 1, но делайте это несколько раз для каждого рендеринга кадра - в зависимости от того, сколько времени прошло - так, чтобы игровая логика продолжала работать в режиме реального времени, оставаясь на дискретных шагах. Таким образом, легко реализовать логику игры, такую ​​как интеграторы Euler и простое обнаружение конфликтов. У вас также есть возможность интерполировать графические анимации на основе дельта-времени, но это только для визуальных эффектов, и ничто не влияет на вашу основную логику игры. У вас могут возникнуть проблемы, если ваши обновления будут очень интенсивными - если обновления отстают, вам нужно будет все больше и больше из них, чтобы они не отставали, потенциально делая вашу игру еще менее отзывчивой.

Лично мне нравится вариант 1, когда я могу уйти с ним и вариант 3, когда мне нужно синхронизировать с реальным временем. Я уважаю, что Вариант 2 может быть хорошим вариантом, когда вы знаете, что делаете, но я знаю свои ограничения достаточно хорошо, чтобы оставаться вдали от него.

ответил 18 J0000006Europe/Moscow 2013, 13:15:59
0

Я обнаружил, что фиксированные временные метки, синхронизированные с 60fps, дают зеркальную гладкую анимацию. Это особенно важно для приложений VR. Все остальное физически тошнотворно.

Переменные временные метки не подходят для VR. Посмотрите примеры Unity VR, которые используют переменные timestep. Это неприятно.

Правило: если ваша 3D-игра гладкая в режиме VR, она будет отличной в режиме без VR.

Сравните эти два (приложения для карточного VR)

(временные интервалы с переменной)

(Исправлены временные интервалы)

Ваша игра должна быть многопоточной, чтобы обеспечить согласованную временную привязку /частоту кадров. Физика, интерфейс и рендеринг должны быть разделены на выделенные потоки. Это отвратительная PITA, чтобы синхронизировать их, но результатом является то, что зеркальный плавный рендеринг вы хотите (особенно для VR).

Мобильные игры - особенно. потому что встроенные процессоры и графические процессоры имеют ограниченную производительность. Используйте GLSL (сленг) экономно, чтобы выгрузить как можно больше работы с ЦП. Имейте в виду, что передача параметров на графический процессор потребляет ресурсы шины.

Всегда сохраняйте частоту кадров во время разработки. Настоящая игра заключается в том, чтобы зафиксировать ее на скорости 60 кадров в секунду. Это основная скорость синхронизации для большинства экранов, а также для большинства глазных яблок.

Используемая вами структура должна быть способна уведомить вас о запросе синхронизации или использовать таймер. Не вставляйте задержку ожидания /ожидания, чтобы добиться этого - даже небольшие изменения заметны.

ответил Dominic Cerisano 3 WedEurope/Moscow2014-12-03T18:45:37+03:00Europe/Moscow12bEurope/MoscowWed, 03 Dec 2014 18:45:37 +0300 2014, 18:45:37
0

Переменные временные шаги предназначены для процедур, которые должны выполняться как можно чаще: циклы визуализации, обработка событий, сетевой материал и т. д.

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

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

Все остальное может работать на переменном шаге времени (хотя профессионально говоря, часто это хорошая идея, позволяющая блокировать рендеринг на фиксированный временной шаг). Для того, чтобы игровой движок реагировал, такие вещи, как сетевые сообщения и пользовательский ввод, должны обрабатываться как можно скорее, а это значит, что интервал между опросами должен быть как можно короче. Обычно это означает переменную.

Все остальное можно обрабатывать асинхронно, заставляя время решать спорные вопросы.

ответил Ian Young 17 +03002017-10-17T13:33:42+03:00312017bEurope/MoscowTue, 17 Oct 2017 13:33:42 +0300 2017, 13:33:42

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132