Концептуально, как воспроизведение работает в игре?

145

Мне было немного любопытно, как воспроизведение может быть реализовано в игре.

Сначала я думал, что будет просто список команд для каждого действия игрока / игрока, которое было предпринято в игре, а затем он «перезапускает» игру и позволяет механизму рендеринга как обычно. Тем не менее, я посмотрел на повторах в FPS / RTS игры, и после тщательного осмотра даже такие вещи , как частицы и графические / звуковые глюки последовательны (и эти глюки , как правило , в последовательной).

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

Стивен Эверс
источник
10
Оригинальные повторы Star Craft были на самом деле НЕ последовательны. Вы можете посмотреть одну и ту же игру дважды и увидеть некоторые довольно разные результаты.
Андрес
1
@ Andres: Интересно, я не заметил. В частности, для жанра RTS я думал о Company Of Heroes.
Стивен Эверс
4
Чтобы прояснить то, что я считаю, SnOrfus спрашивает: некоторые игры (Uncharted 2, Halo 3, даже Battlefield 2) позволяют записать игру целиком. После того, как игра окончена, вы можете воспроизвести ее с назначенной скоростью и пролететь через уровень во время действия, просматривая его с любой точки на карте. Поэтому я предполагаю, что речь идет о записи движений всех игроков / объектов, а не о видеобуфере.
Шон
1
@Sean O'Hollaren: Да, это правильно.
Стивен Эверс
1
Тогда я также добавлю к гоночным играм, где повторы почти по умолчанию. Я почти уверен, что местоположение моделей записано, и тогда все просто запускается через двигатель.
d -_- б

Ответы:

61

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

Питер Рудерман
источник
Номера кадров могут не быть хорошей ссылкой, так как воспроизведение может выполняться с частотой, отличной от живой игры.
Бен С
5
@Ben: частота кадров не имеет значения, так как номера кадров будут оставаться одинаковыми. Это правильный ответ.
BlueRaja - Дэнни Пфлюгофт
14
Графические фреймы и «фреймы» движка (или итерации) не обязательно совпадают. Во многих старых играх движок обновлялся с той же скоростью, что и графика, за один мастер цикл. В современных движках графику часто разрешается обновляться так быстро, как позволяет графический процессор, причем движок движется на уровне, необходимом для хорошего, согласованного разрешения динамики игры (часто это физический движок).
Дэн Брайант
3
@iamgopal: если вы знаете состояние генератора псевдослучайных чисел, то эта проблема уже решена. Другой способ может состоять в том, чтобы рассматривать случайные числа как другую форму ввода и сохранять их вместе с нажатиями клавиш и т.п.
Kylotan
1
Я хотел бы заявить, что этот подход требует, чтобы ваш игровой движок был детерминированным и работал с фиксированным временным шагом. Я считаю, что все игры Blizzard RTS были построены таким образом. Недетерминированные игры будут включать дополнительные данные синхронизации для обеспечения согласованности в долгосрочной перспективе.
Джон Лейдгрен
28

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

Я помню, как однажды смотрел повтор матча, сыгранного в оригинальной игре, но этот просмотр просматривался в Brood War. Для незнакомых людей Brood War содержит все оригинальные юниты и здания, а также множество новых. В оригинальной игре игрок победил компьютер, создав юниты, которые компьютер не мог легко противостоять. Когда я играл в воспроизведение в Brood War, у компьютера был доступ к различным юнитам, которые он создавал и использовал для победы над игроком. Таким образом, один и тот же файл воспроизведения приводил к другому победителю в зависимости от того, какая версия Starcraft воспроизводила файл.

Я всегда находил концепцию увлекательной. Казалось бы, функция воспроизведения работала путем записи всех входов проигрывателя и предполагала, что компьютер будет реагировать на эти раздражители одинаково каждый раз. Когда входные данные игрока были поданы в исходный проигрыватель Starcraft, игра разыгралась точно так же, как и в исходном матче. Когда один и тот же точный ввод был подан в проигрыватель Brood War, компьютер реагировал по-другому, создавал более сильные юниты и выигрывал игру.

Что-то, о чем нужно помнить, если вы пишете движок воспроизведения.

Bobwise
источник
6
+1: очень интересно. Я никогда не слышал об этом. Предоставляет некоторое хорошее представление о том, как они его разработали.
Стивен Эверс
18

Есть два основных метода:

  1. Хранение событий (таких как действия игрока / ай) - так, как вы говорите.
  2. Сохранение состояния (полное игровое состояние, например расположение объектов, в последовательные моменты).

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

Обратите внимание, что «состояние» не означает графическое состояние. Больше что-то вроде позиций юнитов, состояния ресурсов и так далее. Такие вещи, как графика, системы частиц и т. Д., Обычно являются детерминированными и могут быть сохранены как «анимация X, время Y: Z».

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

liori
источник
10

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

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

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

Сделайте все детерминированным, и у вас все будет хорошо.

Тимоти Болдридж
источник
1
А как насчет AI? ИИ не случайный?
Джесси Яшинский
18
Это действительно не обязательно. Используйте псевдослучайные числа для всех случайных событий и сохраните начальное число в файле воспроизведения. Таким образом, одни и те же «случайные» числа будут генерироваться во время воспроизведения.
Бен С
13
-1 за явное недопонимание того, как «случайность» работает в компьютерах
BlueRaja - Дэнни Пфлугхофт
10
эм ... нет .... я прекрасно понимаю, что не существует такой вещи, как "истинная" случайность. Однако большинство людей пытаются обойти это, устанавливая в качестве случайного начального числа что-то вроде системного времени. Однако то, что я говорю, это то, что такое не должно быть сделано. Мне все равно, использует ли он системный API или предопределенную таблицу случайных чисел. То, что я первоначально сказал, было правильно. Каждая функция в его движке должна давать один и тот же результат на основе своих входных данных. Время никогда не должно быть фактором.
Тимоти Болдридж
2
Если частицы не взаимодействуют с игровой механикой каким-либо осмысленным образом, тогда не имеет значения, отличаются ли для них ГСЧ. Это помогло бы в случае симуляции с синхронизацией по сети (как это имеет место в большинстве игр RTS и многих других жанрах игр), поскольку симуляция немного меньше синхронизирует каждый кадр (эффекты частиц просто получают обновляется индивидуально).
RCIX
10

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

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

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

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

Бен С
источник
Если вы будете перезапускать каждое определенное количество секунд (скажем, 5 или 10), было бы достаточно легко выполнить запись в вашем потоке воспроизведения, а также разрешить переход вперед или назад (по существу, для PRNG «ключевых кадров»).
Клин
7

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

Дэн Брайант
источник
4

Ваша оригинальная идея верна, и для действительно сложных эффектов они не запоминаются исключительно. Например, система воспроизведения Warcraft 3 не хранит состояние анимации или эффектов частиц в случае случайных эффектов и т. Д. Кроме того, МОСТ-вещи могут быть вычислены вычислительно из начальной точки детерминистическим способом, так что для большинства систем которые используют случайные переменные (например, взрыв частицы, который дает случайное смещение), все, что вам нужно, это время эффекта и случайное начальное число. Затем вы можете заново сгенерировать эффект, не зная, как он будет выглядеть в конечном итоге… зная, что он проходит через детерминированный путь кода.

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

Стефан Валиану
источник
3

Брось мои два пенса.

Зависит от того, что вы хотите, воспроизведение может быть выполнено через

  1. Запись видео в буфер и воспроизведение позже,
  2. Захватывает состояние объекта каждый кадр и воспроизводит позже,

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

  • убедитесь, что система является детерминированной симуляцией *, так что каждый вход генерирует согласованный и ожидаемый результат
  • если требуется случайность, убедитесь, что случайные числа могут быть точно воспроизведены в более позднее время [посмотрите на засев с помощью генератора псевдослучайных чисел PRNG, или используйте случайные наборы из консервов]
  • разделите игровые элементы на «механические» и «эстетические» элементы. механические элементы влияют на результат [например, падение столбца и блокирование пути], эстетические элементы предназначены для демонстрации и не влияют на процесс принятия решений в системе [например, визуальные эффекты частиц, такие как искры].

Это действительно увлекательная тема. Я помню одно название для запуска оригинальной Xbox Wreckless имел хорошую функцию воспроизведения. К сожалению, в более чем одном случае повтор будет облажаться;)

о да, как можно забыть Blinx Time Sweeper ! отличный интерактивный повтор, который был включен в настоящую игровую механику!


* = Кажется, есть некоторые комментарии относительно временного перехода. Я использую «симуляцию» здесь, чтобы захватить эту функцию. по сути, ваш движок должен быть способен производить дискретные кадры времени. даже если кадр воспроизведения обрабатывается дольше или короче, чем оригинал, система должна понимать, что прошло то же время. это означает запись временного шага кадра с каждого записанного входа и подачу этой дельты на часы вашего двигателя.

Джонни г
источник
2

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

Интересный вопрос, хотя. Мне было бы интересно, как это делается в профессиональных играх.

ThirdD3gree
источник
2

Дэн Брайант

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

Это именно то, о чем я думал вначале, когда пытался выяснить, как они это сделали, чтобы игра повторялась всегда одинаково каждый раз. С Doom я думал о том, насколько случайными были выстрелы: D. Храните любое случайное число, привыкшее, я обнаружил, что это может быть решением. Это было до того, как я наткнулся на статью в формате PDF о технологии Crysis. Некоторые текстуры шумят там, и расположение травы или дерева, кажется, использует псевдослучайное расположение с фиксированным обратимым семенем, чтобы вы не видели измененного расположения шума, деревьев и травы в любое время, когда вы смотрите!

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

антонимичный
источник
Если вы хотите обратить на это внимание Дэна, добавьте комментарий под его вкладом - иначе он, скорее всего, его не увидит.
Halfer
Может быть, это потому, что я просто гость, но я не вижу никакой функции «добавить комментарий» в родительском сообщении, ответил Дэн, не говоря уже об ответе Дана. Я видел, что есть функция редактирования-улучшения, даже для сообщений, которых нет, но как это работает?
Антоним
Ах, хороший вопрос! Здесь кажется, что вам нужно 50 точек для комментариев, чтобы комментировать вопросы или ответы, кроме ваших - мои извинения. 50 очень легко получить, хотя - всего пару полезных вкладов, как правило, для этого. Да, вы можете редактировать вопросы и ответы других людей, хотя ваши изменения будут проверяться другими, пока вы не доберетесь до 2000 года. См. Таблицу привилегий здесь .
Halfer
1

Проблема наличия последовательного повторения такая же (ну, проще), как и постоянная многопользовательская игра.

Как уже упоминалось ранее, повторы в играх RTS сохраняются путем записи всех входных данных (что имеет эффект. Прокрутка не имеет никакого эффекта.) Многопользовательский режим также передает все входные данные.

Запись всех входных данных - не просто предположение - есть библиотека для чтения повторов Warcraft3, которая показывает это.

ввод включает временные метки для этого ответа.

Фрэнки
источник
Нет, это не то же самое (или проще), что и в последовательной игре MP. Когда вы играете в MP, игры обычно требуют, чтобы у всех была одна и та же версия игры, что не обязательно относится к сохраненным сеансам (как это могло быть сохранено в более старой версии игры). Это особенно важно, если один из игроков является противником искусственного интеллекта. Только представьте, что вы воспроизводите игру, в которой у юнита есть только одна точка атаки в более новой версии, чем в той версии, в которой он был записан. Это может привести к совершенно другому результату.
Дракон
-1

Я полагаю, что с определенными приращениями игра будет делать снимок состояния всего (ВСЕ). Затем, когда происходит воспроизведение, можно использовать простую линейную интерполяцию, чтобы заполнить «дыры». По крайней мере, я так думаю.

Вы правы в том, что запись входных данных будет ненадежной / не гарантирует одинаковый выход. В игре обязательно нужно отслеживать состояние всех объектов (или, по крайней мере, важных)

Боб Финхеймер
источник
2
Нет, подача одних и тех же входов приведет к тому же результату, что и в первый раз. Вам просто нужно убедиться, что вы правильно выбрали время, подавая входные данные между теми же кадрами, где они были первоначально получены. Периодическое сохранение всего игрового состояния может потребовать колоссального объема памяти и привести к противоречивым результатам.
Питер Рудерман
@Peter, «подача одинаковых входов приведет к точно такому же результату»: нет. Во многих играх есть случайный элемент, который может отличаться при каждом воспроизведении. Вы должны отслеживать больше, чем входы.
Houbysoft
Это правда. Вам также необходимо хранить семена ваших PRNG (см. Мой ответ на этот вопрос).
Питер Рудерман
1
я знаю, что это потребляет много времени и памяти, но если вы пропустите одну мелочь на входе или на случайных генераторах ... или на самом деле, воспроизведение будет происходить по ужасной касательной!
Боб Финхеймер
@BlueRaja, идея снимка памяти Боба не обязательно является надуманной, хотя хороший движок может записывать «дельты» состояния, а не кодировать всю память для каждой итерации. Это, вероятно, легче поддерживать на уровне двигателя. Кроме того, записи случайных начальных чисел будет недостаточно для поддержки перемотки, поскольку случайная прогрессия не является обратимой процедурой без специальной поддержки во всей логике, основанной на случайности. Более гибко записывать результаты случайных операций как часть потока событий.
Дэн Брайант