Conceptualmente, ¿cómo funciona la repetición en un juego?

145

Tenía curiosidad sobre cómo se podría implementar la repetición en un juego.

Inicialmente, pensé que solo habría una lista de comandos de cada acción de jugador / ai que se tomó en el juego, y luego 'vuelve a jugar' el juego y deja que el motor funcione como de costumbre. Sin embargo, he mirado las repeticiones en FPS / RTS juegos, y después de una inspección cuidadosa incluso cosas como las partículas y fallos gráficos / audibles son consistentes (y esos fallos son por lo general en constante).

Entonces, ¿cómo sucede esto? En los juegos de ángulo de cámara fijo, pensé que podría escribir cada fotograma de toda la escena en una transmisión que se almacena y luego volver a reproducir la transmisión, pero eso no parece suficiente para los juegos que te permiten pausar y mover la cámara alrededor. Tendría que almacenar las ubicaciones de todo en la escena en todos los puntos en el tiempo (¿No?). Entonces, para cosas como las partículas, hay una gran cantidad de datos para impulsar, lo que parece un atractivo significativo en el rendimiento del juego mientras se juega.

Steven Evers
fuente
10
Las repeticiones originales de Star Craft no fueron consistentes. Podrías ver el mismo juego dos veces y ver resultados bastante diferentes.
Andres
1
@ Andreas: Interesante, no me había dado cuenta. En particular, para el género RTS, estaba pensando en Company Of Heroes.
Steven Evers
44
Para aclarar lo que creo que SnOrfus pregunta: Algunos juegos (Uncharted 2, Halo 3, incluso Battlefield 2) te permiten grabar un juego en su totalidad. Una vez finalizado el juego, puedes volver a jugarlo a una velocidad designada y volar a través del nivel mientras se desarrolla la acción, viéndolo desde cualquier posición en el mapa. Así que supongo que se trata de grabar los movimientos de todos los jugadores / objetos y no algo relacionado con el búfer de video.
Sean
1
@Sean O'Hollaren: Sí, eso es correcto.
Steven Evers
1
Luego también agregaré para los juegos de carreras de autos donde las repeticiones son casi predeterminadas. Estoy bastante seguro de que se registra la ubicación de los modelos y luego todo se ejecuta a través del motor.
d -_- b

Respuestas:

61

Creo que tu pensamiento inicial fue correcto. Para crear una repetición, almacena todas las entradas recibidas del usuario (junto con el número de fotograma en el que se recibió) junto con las semillas iniciales de cualquier generador de números aleatorios. Para volver a jugar el juego, reinicia sus PRNG utilizando las semillas guardadas y alimenta al motor del juego con la misma secuencia de entrada (sincronizada con los números de fotograma). Dado que muchos juegos actualizarán el estado del juego en función de la cantidad de tiempo que pasa entre fotogramas, es posible que también deba almacenar la duración de cada fotograma.

Peter Ruderman
fuente
Los números de fotograma pueden no ser una buena referencia ya que la repetición podría ejecutarse a una velocidad de fotogramas diferente que el juego en vivo.
Ben S
55
@Ben: La velocidad de fotogramas no hace la diferencia, ya que los números de fotogramas seguirán siendo los mismos. Esta es la respuesta correcta.
BlueRaja - Danny Pflughoeft
14
Los cuadros gráficos y los 'cuadros' (o iteraciones) del motor no son necesariamente los mismos. En muchos juegos antiguos, el motor se actualizaba al mismo ritmo que los gráficos, en un bucle maestro. Con los motores modernos, a menudo se permite que los gráficos se actualicen tan rápido como lo permita la GPU, con el motor avanzando al nivel requerido para una resolución buena y consistente de la dinámica del juego (a menudo un motor de física).
Dan Bryant
3
@iamgopal: si conoce el estado del generador de números pseudoaleatorios, ese problema ya está resuelto. Otro método puede ser tratar los números aleatorios como otra forma de entrada y guardarlos junto con las pulsaciones de teclas y similares.
Kylotan
1
Me gustaría anunciar que este enfoque requiere que su motor de juego sea determinista y que funcione con un paso de tiempo fijo. Creo que todos los juegos RTS de Blizzard se han construido de esta manera. Los juegos no deterministas incluirían datos de sincronización adicionales para garantizar la coherencia a largo plazo.
John Leidegren
28

Starcraft y Starcraft: Brood War tenían una función de repetición. Después de completar una partida, puedes elegir guardar la repetición para verla más tarde. Durante la reproducción, puede desplazarse por el mapa y hacer clic en unidades y edificios, pero no cambiar su comportamiento.

Recuerdo que una vez vi una repetición de un partido que se había jugado en el juego original, pero la repetición se estaba viendo en Brood War. Para aquellos que no están familiarizados, Brood War contiene todas las unidades y edificios originales, así como una variedad de nuevos. En el juego original, el jugador había derrotado a la computadora creando unidades que la computadora no podía contrarrestar fácilmente. Cuando jugué la repetición en Brood War, la computadora tenía acceso a diferentes unidades, que creó y usó para derrotar al jugador. Entonces, exactamente el mismo archivo de reproducción resultó en un ganador diferente dependiendo de qué versión de Starcraft estaba reproduciendo el archivo.

Siempre encontré el concepto fascinante. Parecería que la función de repetición funcionó grabando todas las entradas del jugador, y asumió que la computadora respondería a esos estímulos exactamente de la misma manera cada vez. Cuando las entradas del jugador se introdujeron en el repetidor original de Starcraft, el juego se desarrolló exactamente igual que en la partida original. Cuando la misma entrada exacta se introdujo en el repetidor de Brood War, la computadora reaccionó de manera diferente, creó unidades más fuertes y ganó el juego.

Algo a tener en cuenta si estás escribiendo un motor de repetición.

Bobwise
fuente
66
+1: muy interesante. Nunca había escuchado sobre eso. Proporciona una buena idea de cómo lo desarrollaron.
Steven Evers
18

Hay dos métodos principales:

  1. Almacenamiento de eventos (como acciones de jugador / ai), tal como usted dice.
  2. Estado de almacenamiento (estado de juego completo, ubicaciones de objetos, en momentos consecutivos).

Depende de lo que quieras hacer. A veces, almacenar eventos es mejor, porque esto generalmente requiere mucha menos memoria. Por otro lado, si desea proporcionar repeticiones que se pueden jugar a diferentes velocidades y desde diferentes puntos de partida, es mejor almacenar estados. Al almacenar estados, también puede decidir si los almacena después de cada evento o solo 12 o 25 veces por segundo; esto podría reducir el tamaño de su repetición y facilitar el rebobinado / avance rápido.

Tenga en cuenta que "estado" no significa estado gráfico. Más algo como puestos de unidad, estado de recursos, etc. Cosas como gráficos, sistemas de partículas, etc., generalmente son deterministas y se pueden almacenar como "animación X, tiempo Y: Z".

A veces las repeticiones se utilizan como esquema anticonceptivo. Entonces almacenar eventos es probablemente el mejor aquí.

liori
fuente
10

Técnicamente, debe escribir su motor para que sea determinista, eso no es aleatoriedad. Suponiendo que un personaje en el juego apunta al brazo de un oponente y dispara un arma, se debe aplicar la misma cantidad de daño al oponente en todos los casos.

Suponiendo que una bomba detona en la ubicación X, las partículas producidas por esa explosión siempre deben dar el mismo resultado visual. Si necesita aleatoriedad, cree un conjunto de números aleatorios, seleccione un valor inicial cuando se juega el juego y guarde ese valor inicial en la repetición.

En general, tener aleatoriedad en un juego es una mala idea. Incluso para cosas como el modo multijugador, no puedes tener la mitad de tus jugadores capaces de ver alrededor de una explosión, mientras que los demás no pueden simplemente porque no obtuvieron el valor aleatorio correcto.

Haz todo determinista, y deberías estar bien.

Timothy Baldridge
fuente
1
¿Qué hay de la IA? ¿La IA no es aleatoria?
Jesse Jashinsky
18
Eso realmente no es necesario. Use números seudoaleatorios sembrados para todos los eventos aleatorios y guarde la semilla en el archivo de reproducción. De esa forma, se generarán los mismos números "aleatorios" durante la repetición.
Ben S
13
-1 por una clara incomprensión de cómo funciona la "aleatoriedad" en las computadoras
BlueRaja - Danny Pflughoeft
10
um ... no ... Soy perfectamente consciente de que no existe la aleatoriedad "verdadera". Sin embargo, la mayoría de las personas intentan evitar esto estableciendo su semilla aleatoria en algo así como la hora del sistema. Sin embargo, lo que digo es que tal cosa no debería hacerse. No me importa si usa la API del sistema o una tabla predefinida de números aleatorios. Lo que dije originalmente era correcto. Cada función en su motor debe producir el mismo resultado en función de sus entradas. El tiempo nunca debería ser un factor.
Timothy Baldridge
2
Si las partículas no tienen interacción con la mecánica del juego de ninguna manera significativa, entonces realmente no importa si los RNG son diferentes para ellos. Esto ayudaría en el caso de una simulación sincronizada en red (como es el caso en la mayoría de los juegos de estrategia en tiempo real, y en muchos otros géneros de juegos), ya que es un poco menos que la simulación tiene que sincronizar cada cuadro (los efectos de partículas simplemente se obtienen actualizado individualmente).
RCIX
10

Dado el estado inicial y una serie de acciones con marcas de tiempo , simplemente siga la secuencia ya que se supone que las acciones grabadas tienen lugar una repetición.

Para que los eventos aleatorios vuelvan a ocurrir exactamente igual, utilice números seudoaleatorios sembrados y guarde la semilla en el archivo de reproducción.

Siempre que use el mismo algoritmo para generar los números aleatorios a partir de la semilla, puede recrear todos los eventos tal como ocurrieron en el juego en vivo sin necesidad de instantáneas completas del estado del juego.

Esto requerirá que las repeticiones se vean secuencialmente , pero eso es bastante normal para las repeticiones del juego (ver Starcraft 2). Si desea permitir el acceso aleatorio a la línea de tiempo, puede tomar instantáneas de estado completo a intervalos establecidos (digamos cada minuto), para saltar alrededor de la línea de tiempo con una granularidad establecida.

Ben S
fuente
Si vuelves a sembrar cada cierto número de segundos (digamos 5 o 10), sería bastante fácil grabar en tu transmisión de reproducción y también permitir saltar hacia adelante o hacia atrás (para PRNG "cuadros clave" esencialmente).
Wedge
7

NVidia PhysX (un motor de simulación física que se usa a menudo en los juegos) es capaz de registrar el estado completo de la escena física a lo largo del tiempo. Esto incorpora cualquier entrada de manejo del motor del juego, lo que significa que no necesita rastrear semillas de números aleatorios como otros han sugerido. Si toma este volcado de escena, puede reproducirlo en una herramienta externa (proporcionada por NVidia), que es muy útil para localizar problemas con sus modelos físicos. Sin embargo, también podría usar el mismo flujo de física para manejar su motor de gráficos, lo que le permitiría tener un control normal de la cámara, ya que solo se han grabado las físicas que manejan los gráficos. En muchos juegos, esto incluye los efectos de partículas (PhysX incluye algunos sistemas de partículas muy sofisticados). En cuanto al sonido, supongo que se graba textualmente (como una secuencia de sonido), pero yo '

Dan Bryant
fuente
4

Su idea original es correcta, y para los efectos realmente complejos, no se recuerdan exclusivamente. Por ejemplo, el sistema de repetición Warcraft 3 no almacena el estado de las animaciones o los efectos de partículas en el caso de efectos aleatorios, etc. Además, la mayoría de las cosas se pueden calcular computacionalmente desde un punto de partida de manera determinista, por lo que para la mayoría de los sistemas que usan variables aleatorias (una explosión de partículas que proporciona un desplazamiento aleatorio, por ejemplo), todo lo que necesitaría es el tiempo del efecto y la semilla aleatoria. Entonces podría volver a generar el efecto sin saber realmente cómo terminará pareciendo ... sabiendo que está pasando por una ruta de código determinista.

Pensando en ello puramente conceptual, para reproducir una línea de tiempo de eventos, todo lo que necesita son las acciones del usuario. El programa reaccionará exactamente de la misma manera, excepto en el caso de variables aleatorias. En este escenario, podría ignorar la aleatoriedad (¿REALMENTE importa si los efectos se ven EXACTAMENTE iguales, o se pueden volver a generar aleatoriamente?) O almacenar el valor de semilla y falsificar la aleatoriedad.

Stefan Valianu
fuente
3

Tira mis dos peniques.

Depende de lo que desee, la repetición se puede lograr a través de

  1. Grabando el búfer de video y reproduciéndolo más tarde,
  2. Capturando el estado del objeto en cada cuadro y reproduciéndolo más tarde,

La mayoría de las veces, la gente quiere una repetición interactiva, así que 2. es el camino a seguir. Luego, dependiendo de sus limitaciones, hay varias formas de optimizar este proceso

  • Asegúrese de que el sistema sea una simulación determinista *, de modo que cada entrada genere una salida consistente y esperada
  • Si se requiere aleatoriedad, asegúrese de que los números aleatorios puedan reproducirse exactamente más adelante [mire la siembra con generadores de números pseudoaleatorios PRNG, o use conjuntos aleatorios enlatados]
  • divide los elementos del juego en elementos "mecánicos" y "estéticos". los elementos mecánicos afectan el resultado [por ejemplo, la columna se cae y bloquea la ruta], los elementos estéticos son para mostrar y no influyen en ningún proceso de toma de decisiones en el sistema [por ejemplo, efectos de partículas visuales como chispas].

Realmente es un tema fascinante. Recuerdo que un título de lanzamiento para Xbox Wreckless original tenía una buena función de reproducción. Desafortunadamente, en más de una ocasión la repetición se arruinaría;)

oh sí, ¿cómo podría alguien olvidar a Blinx Time Sweeper ? ¡Gran reproducción interactiva que se incorporó a la mecánica del juego real!


* = parece que hay algunos comentarios con respecto al paso del tiempo. Estoy usando "simulación" aquí para capturar esta característica. En el fondo, su motor debe ser capaz de producir marcos de tiempo discretos. incluso si un marco de reproducción tarda más o menos en procesarse que el original, el sistema debe percibir que ha pasado el mismo tiempo delta. esto significa registrar el intervalo de tiempo del cuadro con cada entrada grabada y suministrar este delta al reloj del motor.

johnny g
fuente
2

Quizás podrías simplemente guardar una pila de comandos que envía cada jugador. Entonces, en lugar de ahorrar que una bomba detona en un momento y momento determinados, o que un determinado automóvil se destruye, simplemente guarde las pulsaciones de teclas enviadas por cada jugador. Luego, en la repetición, simplemente simulas el juego como hubiera sucedido con esas prensas. Siento que eso tiene el potencial de ocupar menos espacio, pero nunca he trabajado en un sistema de repetición como ese.

Pregunta interesante, sin embargo. Me interesaría cómo se hace en los juegos profesionales.

TercerD3gree
fuente
2

Dan Bryant

Además, registrar semillas aleatorias no sería suficiente para el soporte de rebobinado, ya que la progresión aleatoria no es un procedimiento reversible sin un apoyo especial en toda la lógica que se basa en la aleatoriedad. Es más flexible registrar los resultados de las operaciones aleatorias como parte de la secuencia de eventos.

Eso es exactamente lo que pensé al principio cuando estaba tratando de averiguar cómo lo lograron para que el juego siempre se repita siempre. Con Doom pensé en lo aleatorio que fueron los brotes: D. Almacene cualquier número aleatorio que se haya usado, descubrí que podría ser una solución. Eso fue antes de encontrar un documento en pdf sobre la tecnología Crysis. El ruido de algunas texturas allí y la disposición de la hierba o los árboles, parecían estar usando pseudoaleatorización con semilla reversible fija para que no se vea una disposición alterada del ruido, los árboles y la hierba cada vez que se mira.

Evitando al mismo tiempo, almacenar millones de árboles y posición de pozos de hierba. Aparentemente, la secuencia pseudoaleatoria puede reproducirse en cualquier momento, ya que la lógica es fija, para crear una secuencia de números estadísticamente aleatoria falsa.

Antónimo
fuente
Si desea llamar la atención de Dan sobre esto, agregue un comentario debajo de su contribución; de lo contrario, es probable que no lo vea.
halfer
Podría ser porque solo soy un invitado, pero no pude ver ninguna función de "agregar comentario" en la publicación principal, respondió Dan, y mucho menos la respuesta de Dan. Vi que hay una función de edición-mejora, incluso para publicaciones que no son mías, pero ¿cómo funciona?
Antónimo
Ah, buena pregunta! Se parece aquí que necesita 50 puntos rep hacer comentarios sobre las preguntas o respuestas distintas a la suya - mis disculpas. Sin embargo, 50 es muy fácil de obtener; solo un par de contribuciones útiles generalmente lo lograrán. Sí, puede editar las preguntas y respuestas de otras personas, aunque sus ediciones serán revisadas por otros hasta llegar a 2000. Vea su tabla de privilegios aquí .
halfer
1

El problema de tener una repetición consistente es el mismo (bueno, más fácil) que tener un juego multijugador consistente.

Como otros mencionaron antes, las repeticiones en los juegos RTS se almacenan grabando todas las entradas (eso tiene un efecto. El desplazamiento no tiene ningún efecto). El modo multijugador también transmite todas las entradas.

Grabar todas las entradas, no solo una suposición, hay una biblioteca para leer las repeticiones de Warcraft3 con esto revela.

La entrada incluye marcas de tiempo para esta respuesta.

Franky
fuente
No, no es lo mismo (o más fácil) que un juego de MP consistente. Cuando juegas MP, los juegos generalmente requieren que todos tengan la misma versión del juego, lo cual no es necesariamente el caso para las sesiones almacenadas (ya que puede haber sido almacenado con una versión anterior del juego). Esto es especialmente crítico si uno de los jugadores es un oponente de IA. Solo imagina que vuelves a jugar un juego en el que una unidad solo tiene un punto de ataque más en una versión más nueva que en la versión en la que se grabó. Esto podría conducir a un resultado completamente diferente.
Drakon
-1

Creo que en ciertos incrementos el juego tomaría una instantánea del estado de todo (TODO). Luego, cuando la repetición está ocurriendo, el uso simple de interpolación lineal se puede utilizar para completar los "agujeros". Al menos así es como creo que se haría.

Tiene razón en que registrar las entradas no sería confiable / no garantizaría la misma salida. El juego definitivamente tiene que hacer un seguimiento del estado de todos los objetos (o al menos los más importantes)

Bob Fincheimer
fuente
2
No, alimentar las mismas entradas dará como resultado exactamente el mismo resultado que la primera vez. Solo tiene que asegurarse de obtener la sincronización correcta, alimentando la entrada entre los mismos cuadros donde se recibió originalmente. Guardar el estado completo del juego periódicamente podría requerir una cantidad colosal de memoria y producir resultados inconsistentes también.
Peter Ruderman
@Peter, "alimentar las mismas entradas dará como resultado exactamente el mismo resultado": no. Hay un elemento aleatorio en muchos juegos, que podría ser diferente cada vez que se juega la repetición. Necesita hacer un seguimiento de más de las entradas.
houbysoft
Es verdad. También debe almacenar las semillas de sus PRNG (consulte mi respuesta a esta pregunta).
Peter Ruderman
1
Sé que consume mucho rendimiento y memoria, pero si te pierdes 1 cosita en cuanto a la entrada o los generadores aleatorios ... o realmente cualquier cosa, ¡la repetición se disparará en una tangente horrible!
Bob Fincheimer
@BlueRaja, la idea de la instantánea de memoria de Bob no es necesariamente tan descabellada, aunque un buen motor puede registrar 'deltas' de estado en lugar de codificar toda la memoria para cada iteración. Probablemente sea más fácil de soportar a nivel de motor. Además, registrar semillas aleatorias no sería suficiente para el soporte de rebobinado, ya que la progresión aleatoria no es un procedimiento reversible sin un apoyo especial en toda la lógica que se basa en la aleatoriedad. Es más flexible registrar los resultados de las operaciones aleatorias como parte de la secuencia de eventos.
Dan Bryant