Concettualmente, come funziona il replay in un gioco?


145

Ero un po 'curioso di sapere come il replay potesse essere implementato in un gioco.

Inizialmente, ho pensato che ci sarebbe stato solo un elenco di comandi di ogni azione giocatore / ai che era stata intrapresa nel gioco, e poi 'ri-gioca' il gioco e lascia che il motore si mostri come al solito. Tuttavia, ho guardato i replay in FPS / RTS, e su un'attenta ispezione anche cose come le particelle e glitch grafici / udibili sono coerenti (e quei difetti sono generalmente in linea).

Quindi, come succede? Nei giochi con angolazione fissa della fotocamera, ho pensato che potrebbe solo scrivere ogni fotogramma dell'intera scena su uno stream che viene archiviato e quindi riproduce nuovamente lo stream, ma non sembra abbastanza per i giochi che ti consentono di mettere in pausa e spostare la telecamera in giro. Dovresti memorizzare le posizioni di tutto nella scena in ogni momento (No?). Quindi, per cose come le particelle, ci sono molti dati da spingere che sembrano un significativo richiamo alle prestazioni del gioco durante il gioco.


10
I replay originali di Star Craft NON erano infatti coerenti. Potresti guardare lo stesso gioco due volte e vedere risultati piuttosto diversi.
Andres,

1
@Andres: interessante, non me ne ero accorto. In particolare, per il genere RTS, stavo pensando a Company Of Heroes.
Steven Evers,

4
Per chiarire ciò che credo SnOrfus stia chiedendo: alcuni giochi (Uncharted 2, Halo 3, persino Battlefield 2) consentono di registrare un gioco nella sua interezza. Dopo che il gioco è finito, puoi riprodurlo a una velocità designata e volare attraverso il livello mentre l'azione è in corso, visualizzandolo da qualsiasi posizione sulla mappa. Quindi presumo si tratti di registrare le mosse di tutti i giocatori / oggetti e non qualcosa a che fare con il buffer video.
Sean,

1
@Sean O'Hollaren: Sì, è corretto.
Steven Evers,

1
Quindi aggiungerò anche i giochi di corse automobilistiche in cui i replay sono quasi predefiniti. Sono abbastanza sicuro che la posizione dei modelli sia registrata e quindi tutto passi semplicemente attraverso il motore.
d -_- b

Risposte:


61

Penso che il tuo pensiero iniziale fosse corretto. Per creare un replay, si memorizzano tutti gli input ricevuti dall'utente (insieme al numero di frame in cui è stato ricevuto) insieme ai seed iniziali di eventuali generatori di numeri casuali. Per ripetere il gioco, ripristini i tuoi PRNG usando i semi salvati e dai al motore di gioco la stessa sequenza di input (sincronizzata con i numeri dei frame). Poiché molti giochi aggiornano lo stato del gioco in base alla quantità di tempo che passa tra i frame, potrebbe essere necessario memorizzare la lunghezza di ciascun frame.


I numeri dei fotogrammi potrebbero non essere un buon riferimento poiché il replay potrebbe essere eseguito con un framerate diverso rispetto al gioco live.
Ben S,

5
@Ben: Framerate non fa differenza, poiché i numeri dei fotogrammi saranno sempre gli stessi. Questa è la risposta corretta
BlueRaja - Danny Pflughoeft il

14
I frame grafici e i "frame" (o iterazioni) del motore non sono necessariamente gli stessi. In molti vecchi giochi, il motore si aggiornava alla stessa velocità della grafica, in un ciclo principale. Con i motori moderni, la grafica è spesso autorizzata ad aggiornare il più velocemente possibile dalla GPU, con il motore che ticchetta al livello richiesto per una buona risoluzione coerente delle dinamiche di gioco (spesso un motore fisico).
Dan Bryant,

3
@iamgopal: se conosci lo stato del generatore di numeri pseudo-casuali, quel problema è già risolto. Un altro metodo potrebbe essere quello di trattare i numeri casuali come un'altra forma di input e salvarli insieme ai tasti premuti e simili.
Kylotan,

1
Vorrei annunciare che questo approccio richiede che il motore di gioco sia deterministico e che funzioni con un intervallo di tempo fisso. Credo che tutti i giochi RTS di Blizzard siano stati costruiti in questo modo. I giochi non deterministici includerebbero ulteriori dati di sincronizzazione per garantire coerenza nel lungo periodo.
John Leidegren,

28

Starcraft e Starcraft: Brood War aveva una funzione di riproduzione. Dopo che una partita è stata completata, puoi scegliere di salvare il replay per visualizzarlo in seguito. Durante la riproduzione, è possibile scorrere la mappa e fare clic su unità ed edifici, ma non modificarne il comportamento.

Ricordo di aver visto una volta il replay di una partita giocata nel gioco originale, ma il replay veniva visualizzato in Brood War. Per coloro che non hanno familiarità, Brood War contiene tutte le unità e gli edifici originali, oltre a una varietà di nuovi. Nel gioco originale, il giocatore aveva sconfitto il computer creando unità che il computer non poteva facilmente contrastare. Quando ho giocato al replay in Brood War, il computer ha avuto accesso a diverse unità, che ha creato e usato per sconfiggere il giocatore. Quindi lo stesso identico file di riproduzione ha comportato un vincitore diverso a seconda della versione di Starcraft che stava riproducendo il file.

Ho sempre trovato il concetto affascinante. Sembrerebbe che la funzione di replay abbia funzionato registrando tutti gli input del lettore e ipotizzando che il computer rispondesse a quegli stimoli nello stesso identico modo ogni volta. Quando gli input del giocatore venivano inseriti nel replayer originale di Starcraft, il gioco si svolgeva esattamente come nella partita originale. Quando lo stesso input esatto è stato inserito nel replayer di Brood War, il computer ha reagito in modo diverso, ha creato unità più forti e ha vinto il gioco.

Qualcosa da tenere a mente se stai scrivendo un motore di riproduzione.


6
+1: molto interessante. Non ne avevo mai sentito parlare. Fornisce alcune buone informazioni su come lo hanno sviluppato.
Steven Evers,

18

Esistono due metodi principali:

  1. Memorizzare eventi (come azioni del giocatore / ai) - proprio come dici tu.
  2. Stato di memorizzazione (stato di gioco completo, posizione degli oggetti, in momenti consecutivi).

Dipende da quello che vuoi fare. A volte archiviare gli eventi è meglio, perché di solito richiede molta meno memoria. D'altra parte, se si desidera fornire replay che possono essere riprodotti a velocità diverse e da diversi punti di partenza, è meglio memorizzare gli stati. Quando si memorizzano gli stati è anche possibile decidere se memorizzarli dopo ogni evento o solo 12 o 25 volte al secondo: ciò potrebbe ridurre le dimensioni del replay e facilitare il riavvolgimento / avanzamento rapido.

Si noti che "stato" non significa stato grafico. Più qualcosa come posizioni dell'unità, stato delle risorse e così via. Cose come la grafica, i sistemi di particelle e così via sono generalmente deterministici e possono essere memorizzati come "animazione X, tempo Y: Z".

A volte i replay sono usati come schema anticheating. Quindi la memorizzazione di eventi è probabilmente la migliore qui.


10

Tecnicamente dovresti scrivere il tuo motore per essere deterministico, questa non è casualità. Supponendo che un personaggio del gioco stia mirando al braccio di un avversario e spari un'arma, la stessa quantità di danno dovrebbe essere applicata all'avversario in tutti i casi.

Supponendo che una bomba esploda nella posizione X, le particelle prodotte da quell'esplosione dovrebbero sempre produrre lo stesso risultato visivo. Se hai bisogno di casualità, crea un set di numeri casuali, seleziona un valore seed durante il gioco e salva quel valore seed nel replay.

In generale avere una casualità in un gioco è una cattiva idea. Anche per cose come il multiplayer, non puoi avere la metà dei tuoi giocatori in grado di vedere un'esplosione mentre gli altri non possono semplicemente perché non hanno ottenuto il giusto valore casuale.

Rendi tutto deterministico e dovresti andare bene.


1
Che dire dell'IA? L'intelligenza artificiale non è casuale?
Jesse Jashinsky,

18
Questo non è davvero necessario. Usa numeri pseudo-casuali con seeding per tutti gli eventi casuali e salva il seed nel file di riproduzione. In questo modo verranno generati gli stessi numeri "casuali" durante la riproduzione.
Ben S,

13
-1 per un chiaro fraintendimento di come funziona la "casualità" nei computer
BlueRaja - Danny Pflughoeft

10
um .... no .... sono perfettamente consapevole che non esiste una casualità "vera". Tuttavia, la maggior parte delle persone cerca di aggirare il problema impostando il proprio seme casuale su qualcosa di simile al tempo di sistema. Tuttavia, ciò che sto dicendo è che una cosa del genere non dovrebbe essere fatta. Non mi interessa se utilizza l'API di sistema o una tabella predefinita di numeri casuali. Quello che ho detto inizialmente era corretto. Ogni funzione nel suo motore dovrebbe produrre lo stesso risultato in base ai suoi input. Il tempo non dovrebbe mai essere un fattore.
Timothy Baldridge,

2
Se le particelle non interagiscono in alcun modo con le meccaniche di gioco, non importa se gli RNG sono diversi per loro. Ciò sarebbe d'aiuto nel caso di una simulazione sincronizzata in rete (come nella maggior parte dei giochi RTS e in molti altri generi di giochi), poiché è un po 'meno la simulazione deve sincronizzare ogni fotogramma (gli effetti particellari si ottengono aggiornato singolarmente).
RCIX,

10

Dato lo stato iniziale e una serie di azioni con timestamp , basta seguire la sequenza in quanto si suppone che le azioni registrate abbiano una ripetizione.

Per fare in modo che gli eventi casuali si ripetano esattamente allo stesso modo, utilizzare numeri pseudo-casuali con seeding e salvare il seed nel file di riproduzione.

Finché si utilizza lo stesso algoritmo per generare i numeri casuali dal seme, è possibile ricreare tutti gli eventi così come si sono verificati nel gioco dal vivo senza bisogno di istantanee complete dello stato del gioco.

Ciò richiederà che i replay siano guardati in sequenza , ma è abbastanza normale per i replay di gioco (vedi Starcraft 2). Se si desidera consentire l'accesso casuale alla linea temporale, è possibile eseguire istantanee di stato complete a intervalli prestabiliti (ad esempio ogni minuto), per saltare la linea temporale con una granularità prestabilita.


Se esegui nuovamente il seeding ogni determinato numero di secondi (diciamo 5 o 10), sarebbe abbastanza facile registrare nel tuo stream di replay e consentire anche di saltare avanti o indietro (essenzialmente ai "key frame" di PRNG).
Wed

7

NVidia PhysX (un motore di simulazione fisica spesso utilizzato nei giochi) è in grado di registrare nel tempo l'intero stato della scena fisica. Questo include qualsiasi input di guida dal motore di gioco, il che significa che non è necessario tenere traccia dei semi di numeri casuali come altri hanno suggerito. Se prendi questo dump della scena, puoi riprodurlo in uno strumento esterno (fornito da NVidia), che è molto utile per rintracciare i problemi con i tuoi modelli fisici. Tuttavia, potresti anche utilizzare lo stesso flusso di fisica per guidare il tuo motore grafico, il che ti consentirebbe quindi di avere un normale controllo della fotocamera, poiché è stata registrata solo la fisica che guida la grafica. In molti giochi, questo include gli effetti particellari (PhysX include alcuni sistemi particellari molto sofisticati.) Per quanto riguarda il suono, immagino che sia registrato alla lettera (come flusso sonoro), ma io '


4

La tua idea originale è giusta e, per gli effetti davvero complessi, non sono ricordati esclusivamente. Ad esempio, il sistema di riproduzione di Warcraft 3 non memorizza lo stato delle animazioni o gli effetti particellari nel caso di effetti casuali, ecc. Inoltre, MOLTE cose possono essere calcolate computazionalmente da un punto di partenza in modo deterministico, quindi per la maggior parte dei sistemi che usano variabili casuali (un'esplosione di particelle che fornisce un offset casuale, per esempio), tutto ciò di cui hai bisogno è il tempo dell'effetto e il seme casuale. Potresti quindi rigenerare l'effetto senza sapere davvero come andrà a finire .. sapendo che sta attraversando un percorso di codice deterministico.

Pensandoci in modo puramente concettuale, per riprodurre una sequenza temporale di eventi, tutto ciò che serve sono le azioni dell'utente. Il programma reagirà esattamente allo stesso modo, tranne nel caso di variabili casuali. In questo scenario, potresti ignorare la casualità (importa DAVVERO se gli effetti sembrano ESATTAMENTE gli stessi, oppure possono essere rigenerati casualmente), oppure memorizzare il valore del seme e falsare la casualità.


3

Getto i miei due penny.

Dipende da ciò che desideri, la riproduzione può essere effettuata tramite

  1. Registrazione del buffer video e riproduzione in seguito,
  2. Catturare lo stato dell'oggetto ogni fotogramma e riprodurlo in seguito,

Il più delle volte, le persone vogliono un replay interattivo, quindi 2. è la strada da percorrere. Quindi, a seconda dei vincoli, esistono diversi modi per ottimizzare questo processo

  • assicurarsi che il sistema sia una simulazione deterministica *, in modo tale che ogni input generi un output coerente e previsto
  • se è necessaria la casualità, assicurarsi che i numeri casuali possano essere riprodotti esattamente in un secondo momento [guardare il seeding con PRNG di generatori di numeri casuali pseudo o utilizzare set casuali fissi]
  • dividere gli elementi di gioco in elementi "meccanici" ed "estetici". gli elementi meccanici influenzano il risultato [es. colonna che cade e blocca il percorso], gli elementi estetici sono per lo spettacolo e non influenzano alcun processo decisionale nel sistema [es. effetti di particelle visive come scintille].

È davvero un argomento affascinante. Ricordo che un titolo di lancio per Xbox Wreckless originale aveva una buona funzione di riproduzione. Sfortunatamente, in più di un'occasione il replay avrebbe rovinato;)

oh sì, come si può dimenticare Blinx Time Sweeper ! fantastico replay interattivo incorporato nella meccanica di gioco reale!


* = sembra che ci siano alcuni commenti riguardo al time stepping. sto usando "simulazione" qui per catturare questa funzione. in sostanza, il tuo motore deve essere in grado di produrre intervalli di tempo discreti. anche se l'elaborazione di un fotogramma di riproduzione richiede più tempo o meno rispetto all'originale, il sistema deve percepire che è trascorso lo stesso delta temporale. questo significa registrare il frame time step con ogni input registrato e fornire questo delta al clock del motore.


2

Forse potresti semplicemente salvare una pila di comandi inviati da ciascun giocatore. Quindi, invece di salvare che una bomba esplode in un determinato momento e tempo, o che una determinata auto viene distrutta, è sufficiente salvare le pressioni dei tasti inviate da ciascun giocatore. Quindi, nel replay, simuli semplicemente il gioco come sarebbe successo con quelle macchine da stampa. Sento che ha il potenziale per occupare meno spazio, ma non ho mai lavorato su un sistema di riproduzione simile.

Domanda interessante, però. Sarei interessato a come è fatto nei giochi professionali.


2

Dan Bryant

Inoltre, la registrazione di semi casuali non sarebbe sufficiente per il supporto del riavvolgimento, poiché la progressione casuale non è una procedura reversibile senza un supporto speciale in tutta la logica basata sulla casualità. È più flessibile registrare i risultati delle operazioni casuali come parte del flusso di eventi.

Questo è esattamente quello che ho pensato all'inizio quando stavo cercando di capire come sono riusciti a far sì che il gioco si ripeta sempre lo stesso ogni volta. Con Doom ho pensato a quanto fossero casuali i tiri: D. Memorizza qualsiasi numero casuale usato, ho scoperto che potrebbe essere una soluzione. Questo è stato prima che mi imbattessi in un documento in pdf sulla tecnologia Crysis. Alcune trame rumore lì e disposizione dell'erba o dell'albero, sembravano usare la pseudorandomizzazione con seme reversibile fisso per farlo in modo da non vedere una disposizione alterata di rumore, alberi ed erba ogni volta che guardi!

Evitando allo stesso tempo, di conservare milioni di alberi e posizioni dei fusti d'erba. Apparentemente la sequenza pseudo-casuale può riprodurre lo stesso in qualsiasi momento, poiché la logica è fissa, per creare semplicemente una falsa sequenza statisticamente casuale di numeri.


Se desideri attirare l'attenzione di Dan su questo, aggiungi un commento sotto il suo contributo, altrimenti probabilmente non lo vedrà.
halfer

Potrebbe essere perché sono solo un ospite, ma non ho potuto vedere alcuna funzione "Aggiungi commento" nel post principale, rispose Dan, figuriamoci sulla risposta di Dan. Ho visto che esiste una funzione di modifica e miglioramento, anche per i post che non sono miei, ma come funziona?
Antonymous

Ah, bella domanda! E sembra qui che hai bisogno di 50 punti rep di commentare domande o risposte diverse dalla propria - le mie scuse. 50 è molto facile da ottenere, anche se solo un paio di contributi utili lo raggiungeranno. Sì, puoi modificare le domande e le risposte di altre persone, anche se le tue modifiche saranno esaminate da altri fino a quando non arriverai al 2000. Consulta la tua tabella dei privilegi qui .
halfer

1

Il problema di avere un replay coerente è lo stesso (beh, più facile) come avere un gioco multiplayer coerente.

Come altri già menzionati, i replay nei giochi RTS vengono archiviati registrando tutti gli input (ciò ha un effetto. Lo scrolling non ha alcun effetto.) Il multiplayer trasmette anche tutti gli input

La registrazione di tutti gli input non è solo una supposizione: esiste una libreria per la lettura dei replay di Warcraft3 che rivela questo.

l'input include i timestamp per questa risposta.


No, non è lo stesso (o più facile) di un gioco MP coerente. Quando giochi a MP, i giochi di solito richiedono che tutti abbiano la stessa versione del gioco, il che non è necessariamente il caso delle sessioni memorizzate (poiché potrebbe essere stato memorizzato con una versione precedente del gioco). Ciò è particolarmente critico se uno dei giocatori è un avversario AI. Immagina di riprodurre un gioco in cui un'unità ha solo un punto di attacco in più in una versione più recente rispetto alla versione in cui è stata registrata. Ciò potrebbe portare a un risultato completamente diverso.
drakon,

-1

Credo che a determinati incrementi il ​​gioco farebbe un'istantanea dello stato di tutto (TUTTO). Quindi, quando si verifica la riproduzione, è possibile utilizzare un semplice utilizzo dell'interpolazione lineare per riempire i "buchi". Almeno è così che penso che sarebbe stato fatto.

Hai ragione a dire che la registrazione degli ingressi sarebbe inaffidabile / non garantisce lo stesso output. Il gioco deve sicuramente tenere traccia dello stato di tutti gli oggetti (o almeno di quelli importanti)


2
No, l'alimentazione degli stessi input produrrà esattamente lo stesso risultato della prima volta. Devi solo assicurarti di avere il tempismo corretto, alimentando l'input tra gli stessi frame in cui è stato originariamente ricevuto. Salvare periodicamente l'intero stato del gioco potrebbe richiedere una quantità colossale di memoria e produrre anche risultati incoerenti.
Peter Ruderman,

@Peter, "alimentare gli stessi input produrrà esattamente lo stesso risultato": no. C'è un elemento casuale in molti giochi, che potrebbe essere diverso ogni volta che si gioca il replay. È necessario tenere traccia di più degli input.
houbysoft,

È vero. Devi anche conservare i semi dei tuoi PRNG (vedi la mia risposta a questa domanda).
Peter Ruderman,

1
so che è un consumo di prestazioni e memoria, ma se ti manca 1 piccola cosa per quanto riguarda l'input o i generatori casuali ... o davvero qualsiasi cosa, il replay si spegnerà su una tangente orribile!
Bob Fincheimer,

@BlueRaja, l'idea di un'istantanea della memoria di Bob non è necessariamente così inverosimile, anche se un buon motore può registrare 'delta' di stato piuttosto che codificare tutta la memoria per ogni iterazione. Questo è probabilmente più facile da supportare a livello di motore. Inoltre, la registrazione di semi casuali non sarebbe sufficiente per il supporto del riavvolgimento, poiché la progressione casuale non è una procedura reversibile senza un supporto speciale in tutta la logica basata sulla casualità. È più flessibile registrare i risultati delle operazioni casuali come parte del flusso di eventi.
Dan Bryant,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.