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.
fuente
Respuestas:
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.
fuente
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.
fuente
Hay dos métodos principales:
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í.
fuente
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.
fuente
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.
fuente
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 '
fuente
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.
fuente
Tira mis dos peniques.
Depende de lo que desee, la repetición se puede lograr a través de
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
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.
fuente
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.
fuente
Dan Bryant
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.
fuente
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.
fuente
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)
fuente