Come posso eseguire una simulazione di fisica deterministica?


43

Sto creando un gioco di fisica che coinvolge corpi rigidi in cui i giocatori muovono pezzi e parti per risolvere un puzzle / mappa. Un aspetto estremamente importante del gioco è che quando i giocatori iniziano una simulazione, lo stesso funziona ovunque , indipendentemente dal loro sistema operativo, processore, ecc ...

C'è spazio per molta complessità e le simulazioni possono essere eseguite a lungo, quindi è importante che il motore fisico sia completamente deterministico per quanto riguarda le sue operazioni in virgola mobile, altrimenti una soluzione potrebbe sembrare "risolvere" sulla macchina di un giocatore e "fallire" su un altro.

Come posso accettare questo determinismo nel mio gioco? Sono disposto a utilizzare una varietà di framework e linguaggi, tra cui Javascript, C ++, Java, Python e C #.

Sono stato tentato da Box2D (C ++) e dai suoi equivalenti in altre lingue, poiché sembra soddisfare le mie esigenze, ma manca di determinismo in virgola mobile, in particolare con funzioni trigonometriche.

L'opzione migliore che ho visto finora è stata l'equivalente Java di Box2D (JBox2D). Sembra fare un tentativo di determinismo in virgola mobile usando StrictMathpiuttosto che Mathper molte operazioni, ma non è chiaro se questo motore garantirà tutto ciò di cui ho bisogno in quanto non ho ancora costruito il gioco.

È possibile utilizzare o modificare un motore esistente per soddisfare le mie esigenze? O dovrò costruire un motore da solo?

EDIT: Salta il resto di questo post se non ti interessa il motivo per cui qualcuno avrebbe bisogno di tale precisione. Gli individui nei commenti e nelle risposte sembrano credere che sto cercando qualcosa che non dovrei, e come tale, spiegherò ulteriormente come dovrebbe funzionare il gioco.

Al giocatore viene dato un puzzle o un livello, che contiene ostacoli e un obiettivo. Inizialmente, una simulazione non è in esecuzione. Possono quindi utilizzare pezzi o strumenti forniti loro per costruire una macchina. Una volta premuto start, inizia la simulazione e non è più possibile modificare la propria macchina. Se la macchina risolve la mappa, il giocatore ha superato il livello. Altrimenti, dovranno premere stop, modificare la macchina e riprovare.

Il motivo per cui tutto deve essere deterministico è perché ho intenzione di produrre codice che mapperà ogni macchina (un insieme di pezzi e strumenti che tenta di risolvere un livello) su un file xml o json registrando la posizione, le dimensioni e la rotazione di ogni pezzo. Sarà quindi possibile per i giocatori condividere le soluzioni (che sono rappresentate da questi file) in modo da poter verificare le soluzioni, imparare gli uni dagli altri, organizzare competizioni, collaborare, ecc ... Certo, la maggior parte delle soluzioni, in particolare quelle semplici o veloci quelli, non saranno influenzati da una mancanza di determinismo. Ma i progetti lenti o complessi che risolvono livelli davvero difficili potrebbero essere quelli che saranno probabilmente i più interessanti e che vale la pena condividere.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat . Se ritieni di avere una soluzione al problema, considera di pubblicarlo come una risposta piuttosto che come un commento: questo rende più semplice la modifica, la valutazione tramite votazione / marcatura accettata o commentare direttamente il suggerimento stesso per il feedback piuttosto che tessendo le risposte in un thread di conversazione più lungo.
DMGregory

Risposte:


45

Gestire i numeri in virgola mobile in modo deterministico

Il virgola mobile è deterministico. Bene, dovrebbe essere. È complicato.

C'è molta letteratura sui numeri in virgola mobile:

E come sono problematici:

Per astratto. Almeno, su un singolo thread, le stesse operazioni, con gli stessi dati, avvenute nello stesso ordine, dovrebbero essere deterministiche. Quindi, possiamo iniziare preoccupandoci degli input e riordinando.


Uno di questi input che causa problemi è il tempo.

Prima di tutto, dovresti sempre calcolare lo stesso timestep. Non sto dicendo di non misurare il tempo, sto dicendo che non passerai il tempo alla simulazione fisica, perché le variazioni nel tempo sono una fonte di rumore nella simulazione.

Perché si misura il tempo se non lo si passa alla simulazione fisica? Si desidera misurare il tempo trascorso per sapere quando deve essere chiamato un passaggio di simulazione e - supponendo che si stia utilizzando il sonno - quanto tempo per dormire.

Così:

  • Misura tempo: Sì
  • Usa il tempo nella simulazione: No

Ora, riordino delle istruzioni.

Il compilatore potrebbe decidere che f * a + bè lo stesso di b + f * a, tuttavia che potrebbe avere un risultato diverso. Potrebbe anche compilare in fmadd , oppure potrebbe decidere di prendere più righe come quelle che accadono insieme e scriverle con SIMD , o qualche altra ottimizzazione a cui non riesco a pensare in questo momento. E ricorda che vogliamo che le stesse operazioni avvengano nello stesso ordine, è ovvio che vogliamo controllare quali operazioni avvengono.

E no, usare double non ti salverà.

È necessario preoccuparsi del compilatore e della sua configurazione, in particolare per sincronizzare i numeri in virgola mobile attraverso la rete. Devi fare in modo che le build accettino di fare la stessa cosa.

Probabilmente, scrivere l'assemblea sarebbe l'ideale. In questo modo decidi quale operazione fare. Tuttavia, ciò potrebbe rappresentare un problema per il supporto di più piattaforme.

Così:


Il caso dei numeri a virgola fissa

A causa del modo in cui i float sono rappresentati in memoria, i valori di grandi dimensioni perderanno precisione. È ovvio che mantenere i valori piccoli (clamp) mitiga il problema. Quindi, nessuna velocità enorme e nessuna stanza grande. Ciò significa anche che puoi usare la fisica discreta perché hai meno rischi di tunnel.

D'altra parte, si accumuleranno piccoli errori. Quindi, troncare. Voglio dire, ridimensionare e trasmettere a un tipo intero. In questo modo sai che non sta succedendo nulla. Ci saranno operazioni che puoi fare rimanendo con il tipo intero. Quando devi tornare in virgola mobile, esegui il cast e annulla il ridimensionamento.

Nota dico scala. L'idea è che 1 unità sarà effettivamente rappresentata come una potenza di due (16384 per esempio). Qualunque cosa sia, rendila una costante e usala. In pratica lo stai usando come numero in virgola fissa. In effetti, se è possibile utilizzare molto meglio i numeri a virgola fissa di una libreria affidabile.

Sto dicendo troncato. Per quanto riguarda il problema degli arrotondamenti, significa che non puoi fidarti dell'ultimo bit di qualunque valore tu abbia ottenuto dopo il cast. Quindi, prima della scala del cast per ottenere un po 'più del necessario e troncarlo in seguito.

Così:

  • Mantenere i valori piccoli: Sì
  • Arrotondamento attento: Sì
  • Numeri in punti fissi quando possibile: Sì

Aspetta, perché hai bisogno di virgola mobile? Non potresti lavorare solo con un tipo intero? Oh giusto. Trigonometria e radicazione. Puoi calcolare le tabelle per la trigonometria e la radicazione e farle cuocere nella tua fonte. In alternativa, è possibile implementare gli algoritmi utilizzati per calcolarli con il numero in virgola mobile, ad eccezione dell'utilizzo di numeri in virgola fissa. Sì, è necessario bilanciare memoria, prestazioni e precisione. Tuttavia, potresti rimanere fuori dai numeri in virgola mobile e rimanere deterministico.

Sapevi che hanno fatto cose del genere per la PlayStation originale? Per favore, incontra il mio cane, patch .

A proposito, non sto dicendo di non usare la virgola mobile per la grafica. Solo per la fisica. Voglio dire, certo, le posizioni dipenderanno dalla fisica. Tuttavia, come sai, un collider non deve abbinare un modello. Non vogliamo vedere i risultati del troncamento dei modelli.

Pertanto: UTILIZZARE NUMERI DI PUNTI FISSI.


Per essere chiari, se puoi usare un compilatore che ti consente di specificare come funzionano i punti mobili e che è abbastanza per te, allora puoi farlo. Questa non è sempre un'opzione. Inoltre, lo stiamo facendo per determinismo. I numeri a virgola fissa non significano che non ci siano errori, dopo tutto hanno una precisione limitata.

Non credo che "i numeri in virgola fissa siano difficili" è una buona ragione per non usarli. E se vuoi una buona ragione per usarli, è il determinismo, in particolare il determinismo su tutte le piattaforme.


Guarda anche:


Addendum : sto suggerendo di mantenere piccole le dimensioni del mondo. Detto questo, sia OP che Jibb Smart evidenziano il fatto che allontanarsi dai galleggianti di origine ha meno precisione. Ciò avrà un effetto sulla fisica, uno che sarà visto molto prima del limite del mondo. I numeri a virgola fissa, beh, hanno una precisione fissa, saranno ugualmente buoni (o cattivi, se preferisci) ovunque. Il che è positivo se vogliamo determinismo. Voglio anche menzionare che il modo in cui normalmente facciamo la fisica ha la proprietà di amplificare piccole variazioni. Vedi The Butterfly Effect - Deterministic Physics in The Incredible Machine and Contraption Maker .


Un altro modo di fare fisica

Ho pensato, il motivo per cui il piccolo errore di precisione nei numeri in virgola mobile si amplifica è perché stiamo facendo iterazioni su quei numeri. Ogni passaggio di simulazione prendiamo i risultati dell'ultimo passaggio di simulazione e facciamo cose su di essi. Accumulo di errori in cima ad errori. Questo è il tuo effetto farfalla.

Non credo che vedremo un singolo build utilizzando un singolo thread sulla stessa macchina che genererà output diversi dallo stesso input. Eppure, su un'altra macchina potrebbe, o potrebbe essere una build diversa.

C'è un argomento per testare lì. Se decidiamo esattamente come dovrebbero funzionare le cose e possiamo testare sull'hardware di destinazione, non dovremmo creare build con un comportamento diverso.


Tuttavia, c'è anche un argomento per non lavorare in trasferta che accumula così tanti errori. Forse questa è un'opportunità per fare fisica in modo diverso.

Come forse saprai, esiste una fisica continua e discreta, entrambe lavorano su quanto ciascun oggetto avanzerebbe nel momento in cui si verifica la data. Tuttavia, la fisica continua ha i mezzi per capire l'istante della collisione invece di sondare diversi istanti possibili per vedere se si è verificata una collisione.

Pertanto, sto proponendo quanto segue: utilizzare le tecniche della fisica continua per capire quando accadrà la prossima collisione di ciascun oggetto, con un grande intervallo di tempo, molto più grande di quello di un singolo passaggio di simulazione. Quindi prendi l'istante di collisione più vicino e scopri dove sarà tutto in quell'istante.

Sì, questo è molto lavoro di un singolo passaggio di simulazione. Ciò significa che la simulazione non si avvierà all'istante ...

... Tuttavia, è possibile simulare i passaggi di simulazione successivi senza controllare ogni volta la collisione, poiché si sa già quando si verificherà la collisione successiva (o che non si verifica alcuna collisione nel timestep di grandi dimensioni). Inoltre, gli errori accumulati in quella simulazione sono irrilevanti perché una volta che la simulazione raggiunge il grande timestep, posizioniamo semplicemente le posizioni calcolate in precedenza.

Ora, possiamo usare il budget temporale che avremmo usato per verificare le collisioni in ogni fase della simulazione per calcolare la collisione successiva dopo quella trovata. Cioè possiamo simulare in anticipo usando il timestep di grandi dimensioni. Supponendo che un mondo di portata limitata (questo non funzionerà per giochi enormi), ci dovrebbe essere una coda di stati futuri per la simulazione, e quindi ogni fotogramma che interpoli dall'ultimo stato a quello successivo.


Vorrei discutere per l'interpolazione. Tuttavia, dato che ci sono accelerazioni, non possiamo semplicemente interpolare tutto allo stesso modo. Invece dobbiamo interpolare tenendo conto dell'accelerazione di ciascun oggetto. Per questo motivo, potremmo semplicemente aggiornare la posizione nello stesso modo in cui facciamo per il timestep di grandi dimensioni (il che significa anche che è meno soggetto a errori perché non utilizzeremmo due implementazioni diverse per lo stesso movimento).


Nota : se stiamo eseguendo questi numeri in virgola mobile, questo approccio non risolve il problema degli oggetti che si comportano in modo diverso tanto più lontano dall'origine che sono. Tuttavia, mentre è vero che la precisione si perde quanto più si allontana dall'origine, ciò è ancora deterministico. In effetti, questo è il motivo per cui non è stato nemmeno sollevato inizialmente.


appendice

Da OP nel commento :

L'idea è che i giocatori saranno in grado di salvare le loro macchine in un formato (come xml o json), in modo che la posizione e la rotazione di ogni pezzo vengano registrate. Quel file xml o json verrà quindi utilizzato per riprodurre la macchina sul computer di un altro lettore.

Quindi, nessun formato binario, giusto? Ciò significa che dobbiamo anche preoccuparci che i numeri in virgola mobile recuperati corrispondano o meno all'originale. Vedi: Float Precision Revisited: Portabilità del galleggiante a nove cifre


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Vaillancourt

2
Bella risposta! Altri 2 punti a favore del punto fisso: 1. il virgola mobile si comporterà in modo diverso più vicino o più lontano dall'origine (se hai lo stesso puzzle in un posto diverso), ma il punto fisso non lo farà; 2. il punto fisso ha in realtà più precisione del punto mobile per la maggior parte della sua portata - puoi ottenere precisione usando bene il punto fisso
Jibb Smart

È possibile codificare i dati binari in XML e JSON usando gli base64elementi. Non è un modo efficace per rappresentare grandi quantità di tali dati, ma è errato implicare che impediscono l'uso di rappresentazioni binarie.
Pikalek,

1
@Pikalek Sono consapevole, OP me lo ha chiesto nei commenti, ho citato base64 come opzione, tra gli altri, incluso hex, reinterpreta il cast come int e usando il formato protobuf poiché nessuno capirà comunque quei file, non lo sono (non addestrati ) leggibile dall'uomo. Quindi - suppongo - una mod ha rimosso i commenti (no, non è nella chat collegata sopra). Succederà di nuovo? Devo rimuoverlo dalla risposta? Dovrei allungarlo?
Theraot

@Theraot Ah, posso vedere come avrei potuto interpretarlo diversamente nel contesto di commenti cancellati da allora. (FWIW, ho letto le chat sia su questa risposta che sulla domanda). E anche se esistesse un modo nativo ed efficiente per codificare i dati, c'è ancora la questione più grande di assicurarsi che significhi la stessa cosa su tutte le piattaforme. Dato il churn, forse è meglio lasciarlo così com'è. Grazie per il chiarimento!
Pikalek,

6

Lavoro per un'azienda che realizza un noto gioco di strategia in tempo reale e posso dirti che il determinismo in virgola mobile è possibile.

L'uso di compilatori diversi o lo stesso compilatore con impostazioni diverse o persino versioni diverse dello stesso compilatore possono interrompere il determinismo.

Se hai bisogno di un gioco incrociato tra piattaforme o versioni di gioco, penso che dovresti andare a virgola fissa - l'unico possibile gioco incrociato di cui sono a conoscenza con virgola mobile, è tra PC e XBox1, ma è piuttosto folle.

Dovrai trovare un motore fisico completamente deterministico, oppure prendere un motore open source e renderlo deterministico, oppure avviare il tuo motore. In cima alla mia testa, ho la sensazione che l'Unità di tutte le cose abbia aggiunto un motore di fisica deterministica, ma non sono sicuro che sia solo deterministico sulla stessa macchina o deterministico su tutte le macchine.

Se hai intenzione di provare a girare le tue cose, alcune cose che possono aiutare:

  • I float IEE754 sono deterministici se non stai facendo qualcosa di troppo fruttato (google "determinismo IEE754" per maggiori informazioni su ciò che è o non è coperto)
  • È necessario assicurarsi che ogni client abbia la modalità di arrotondamento e la precisione impostate in modo identico (utilizzare controlfp per impostarlo)
  • la modalità di arrotondamento e la precisione possono essere modificate da alcune librerie matematiche, quindi se stai usando librerie chiuse, potresti volerle controllare dopo aver effettuato le chiamate (usando di nuovo controlfp per verificare)
  • alcune istruzioni SIMD sono deterministiche, molte no, fai attenzione
  • come accennato in precedenza, per garantire il determinismo è necessario anche la stessa piattaforma, la stessa versione esatta dello stesso compilatore, compilando la stessa configurazione, con le stesse impostazioni del compilatore
  • costruire alcuni strumenti per rilevare i desincronismi di stato e aiutare a diagnosticarli, ad esempio CRC lo stato del gioco ogni frame per rilevare quando si verifica una desincronizzazione, quindi disporre di una modalità di registrazione dettagliata che è possibile abilitare laddove le modifiche allo stato del gioco sono laboriosamente registrate in un file, quindi prendi 2 file dalle simulazioni che si sono desincronizzati e confrontali in uno strumento diff per vedere dove è andato storto
  • inizializza tutte le tue variabili nello stato di gioco, la principale fonte di desincronizzazione
  • l'intera simulazione del gioco deve avvenire esattamente nello stesso ordine ogni volta per evitare la desincronizzazione, è incredibilmente facile sbagliare, è consigliabile strutturare la simulazione del gioco in modo tale da minimizzarla. In realtà non sono un tipo di modello di progettazione software, ma per questo caso è probabilmente una buona idea - potresti considerare un tipo di modello in cui la simulazione del gioco è come una scatola sicura e l'unico modo per mutare lo stato del gioco è inserire "messaggi" o "comandi", con accesso costante a qualsiasi cosa al di fuori dello stato del gioco (ad es. rendering, rete, ecc.). Quindi collegare in rete la simulazione per una partita multiplayer è un caso di invio di questi comandi in rete, oppure riprodurre la stessa simulazione è un caso di registrazione del flusso di comandi la prima volta,

1
Unity sta infatti lavorando verso un obiettivo di determinismo multipiattaforma con il suo nuovo sistema Unity Physics per il loro stack tecnologico orientato ai dati, ma a quanto ho capito, è ancora un lavoro in corso e non ancora completo / pronto per l'uso da scaffale.
DMGregory

Qual è un esempio di istruzione SIMD non deterministica? Stai pensando a quelli approssimativi come rsqrtps?
Ruslan,

@DMGregory allora deve essere in anteprima, dato che puoi già usarlo - ma come dici tu potrebbe non essere ancora finito.
Joe,

@Ruslan si rsqrtps / rcpps i risultati dipendono dall'implementazione
Joe

5

Non sono sicuro se questo è il tipo di risposta che stai cercando, ma un'alternativa potrebbe essere quella di eseguire i calcoli su un server centrale. Chiedi ai client di inviare la configurazione al tuo server, di eseguire la simulazione (o di recuperarne una memorizzata nella cache) e di rispedire i risultati, che vengono quindi interpretati dal client ed elaborati in grafica.

Ovviamente, questo interrompe qualsiasi piano che potrebbe essere necessario eseguire il client in modalità offline e, a seconda della complessità computazionale delle simulazioni, potrebbe essere necessario un server molto potente. O più, ma almeno hai la possibilità di assicurarti che abbiano la stessa configurazione hardware e software. Una simulazione in tempo reale potrebbe essere difficile ma non impossibile (pensa ai flussi video in diretta: funzionano, ma con un leggero ritardo).


1
Sono completamente d'accordo. Ecco come garantire un'esperienza condivisa con tutti gli utenti. gamedev.stackexchange.com/questions/6645/… discute un argomento simile, confrontando la differenza tra fisica lato client e fisica lato server.
Tim Holt,

1

Darò un suggerimento contro-intuitivo che, sebbene non affidabile al 100%, dovrebbe funzionare bene per la maggior parte del tempo ed è molto facile da implementare.

Ridurre la precisione.

Usa una dimensione di passo temporale costante predeterminata, esegui la fisica su ogni passo temporale in un galleggiante standard a doppia precisione, ma poi quantifica la risoluzione di tutte le variabili a precisione singola (o qualcosa di ancora peggio) dopo ogni passo. Quindi la maggior parte delle possibili deviazioni che il riordino in virgola mobile potrebbe eventualmente introdurre (rispetto a una corsa di riferimento dello stesso programma) verrà eliminata perché tali deviazioni si verificano in cifre che non esistono nemmeno nella precisione ridotta. Quindi la deviazione non ha la possibilità di un accumulo di Lyapunov (effetto farfalla) che alla fine diventerebbe notevole.

Ovviamente, la simulazione sarà leggermente meno accurata di quanto potrebbe essere (rispetto alla fisica reale), ma ciò non è davvero notevole fintanto che tutte le esecuzioni del programma sono imprecise allo stesso modo .

Ora, tecnicamente parlando, è ovviamente possibile che un riordino provochi una deviazione che raggiunga una cifra di significato più elevato, ma se le deviazioni sono in realtà solo causate dal galleggiante e i tuoi valori rappresentano quantità fisiche continue, questo è estremamente improbabile. Si noti che ci sono mezzo miliardo di doublevalori tra due qualsiasi single, quindi ci si può aspettare che la stragrande maggioranza dei tempi nella maggior parte delle simulazioni sia esattamente la stessa tra le corse di simulazione. I pochi casi in cui una deviazione riesce a superare la quantizzazione si spera saranno in simulazioni che non durano così a lungo (almeno non con dinamiche caotiche).


Consiglierei anche di considerare l'approccio completamente opposto a quello che stai chiedendo: abbraccia l'incertezza ! Se il comportamento è leggermente non deterministico, allora questo è in realtà più vicino agli attuali esperimenti di fisica. Quindi, perché non randomizzare deliberatamente i parametri di partenza per ciascuna corsa di simulazione e renderlo un requisito che la simulazione abbia successo in modo coerente su più prove? Questo insegnerà molto di più sulla fisica e su come progettare le macchine in modo che siano abbastanza robuste / lineari, piuttosto che super fragili che sono realistiche solo in una simulazione.


L'arrotondamento non aiuta, perché se il risultato di alta precisione non è deterministico, alla fine un risultato andrà in una direzione su un sistema e sull'altro su un altro sistema. Ad esempio, è sempre possibile arrotondare per difetto all'intero più vicino, ma poi un computer di sistema 1.0 e l'altro calcola 0.99999999999999999999999999999999999999999999 e arrotondano in modo diverso.
yoyo

Sì, è possibile, come ho già detto nella risposta. Ma accadrà estremamente di rado , così come altri difetti nella fisica del gioco. Così arrotondamento fa aiuto. (Non vorrei arrotondare per
difetto

0

Crea la tua classe per la memorizzazione dei numeri!

Puoi forzare un comportamento deterministico se sai esattamente come verranno eseguiti i calcoli. Ad esempio, se le uniche operazioni da affrontare sono moltiplicazione, divisione, addizione e sottrazione, sarebbe sufficiente rappresentare tutti i numeri come solo un numero razionale. Per fare questo, una semplice classe Rational farebbe bene.

Ma se vuoi trattare calcoli più complicati (possibilmente funzioni trigonometriche per esempio), dovrai scrivere tali funzioni da solo. Se vuoi essere in grado di prendere il seno di un numero, dovresti essere in grado di scrivere una funzione che si avvicina al seno di un numero usando solo le operazioni sopra menzionate. Tutto ciò è fattibile, e secondo me elude gran parte dei dettagli pelosi in altre risposte. Il compromesso è che invece dovrai affrontare un po 'di matematica.


3
L'aritmetica razionale è assolutamente inattuabile per qualsiasi tipo di integrazione numerica. Anche se ogni passo temporale lo fa, * / + -i denominatori diventeranno sempre più grandi nel tempo.
lasciato il

Mi aspetto che anche senza considerare l'integrazione, questa non sarebbe una buona soluzione perché dopo solo un paio di moltiplicazioni o divisioni, i numeri che rappresentano il tuo numeratore e denominatore supererebbero un numero intero a 64 bit.
jvn91173,

0

C'è una certa confusione di terminologia qui. Un sistema fisico può essere completamente deterministico, ma impossibile da modellare per un periodo di tempo utile perché il suo comportamento è estremamente sensibile alle condizioni iniziali e un cambiamento infinitamente minimo nelle condizioni iniziali produrrà comportamenti completamente diversi.

Ecco un video di un dispositivo reale il cui comportamento è intenzionalmente imprevedibile, tranne in senso statistico:

https://www.youtube.com/watch?v=EvHiee7gs9Y

È facile costruire semplici sistemi matematici (usando solo l'aggiunta e la moltiplicazione) in cui il risultato dopo N passi dipende dall'ennesimo decimale delle condizioni di partenza. Scrivere software per modellare costantemente tale sistema, su qualsiasi hardware e software dell'utente potrebbe essere vicino, è quasi impossibile - anche se hai un budget abbastanza grande per il test l'applicazione su ogni probabile combinazione di hardware e software.

Il modo migliore per risolvere questo problema è attaccare il problema alla fonte: rendere la fisica del tuo gioco tanto deterministica quanto deve essere per ottenere risultati riproducibili.

L'alternativa è cercare di renderlo deterministico modificando il software del computer per modellare qualcosa che non lo è quello che la fisica ha specificato. Il problema è che hai introdotto molti più livelli di complessità nel sistema, rispetto al cambiamento esplicito della fisica.

Come esempio specifico, supponiamo che il tuo gioco comporti collisioni tra corpi rigidi. Anche se si ignora l'attrito, in pratica è impossibile modellare esattamente le collisioni tra oggetti di forma arbitraria che possono ruotare mentre si muovono. Ma se cambi la situazione in modo che gli unici oggetti siano mattoni rettangolari non rotanti, la vita diventa molto più semplice. Se gli oggetti nel tuo gioco non sembrano mattoni, nascondi questo fatto con una grafica "non fisica" - ad esempio nascondi letteralmente l'istante di collisione dietro un po 'di fumo o fiamme o una bolla di testo "Ouch" o qualunque altra cosa.

Il giocatore deve scoprire la fisica del gioco giocando. Non importa se non è "totalmente realistico" fintanto che è auto-coerente e abbastanza simile all'esperienza di buonsenso da essere plausibile.

Se fai in modo che la fisica stessa si comporti in modo stabile, un suo modello al computer può anche produrre risultati stabili, almeno nel senso che gli errori di arrotondamento saranno irrilevanti.


1
Non vedo alcuna confusione nella terminologia. L'OP vuole un comportamento deterministico da un sistema potenzialmente caotico. È del tutto fattibile.
Segna il

L'uso di forme più semplici (come cerchi e rettangoli) non modifica affatto il problema. Hai ancora bisogno di molte funzioni trigonometriche, sqrt, ecc ...
jvn91173

-1

Utilizzare la precisione in virgola mobile doppia , anziché la precisione in virgola mobile singola . Sebbene non sia perfetto, è abbastanza preciso da essere considerato deterministico nella tua fisica. Puoi inviare un razzo sulla luna con precisione a doppio virgola mobile, ma non con precisione a singolo virgola mobile.

Se hai davvero bisogno di un determinismo perfetto, usa la matematica a virgola fissa . Questo ti darà meno precisione (supponendo che tu usi lo stesso numero di bit), ma risultati deterministici. Non sono a conoscenza di alcun motore fisico che utilizza la matematica a virgola fissa, quindi potrebbe essere necessario scriverne uno proprio se si desidera seguire questa strada. (Qualcosa che consiglierei contro.)


11
L'approccio a doppia precisione corre contro l'effetto farfalla . In un sistema dinamico (come una sim di fisica), anche una piccola deviazione nelle condizioni iniziali può amplificare attraverso il feedback, aumentando fino a un errore percepibile. Tutte le cifre extra fanno è ritardare un po 'di più - costringendo la palla di neve a rotolare un po' più avanti prima che diventi abbastanza grande da causare problemi.
DMGregory

2
Due errori contemporaneamente: 1) I punti in virgola mobile doppi subiscono gli stessi problemi e di solito rimandano il problema in un futuro sempre più difficile da eseguire il debug. 2) Non esiste una regola che stabilisca che il punto fisso debba essere meno preciso del punto mobile. A seconda della scala e del problema attuale o della memoria che si è pronti per l'uso per numero di punto fisso, possono essere meno precisi, ugualmente precisi o più precisi. Non ha senso dire "sono meno precisi".
phresnel

@phresnel, come esempio di precisione a virgola fissa, la serie IBM 1400 utilizzava matematica decimale a virgola fissa a precisione arbitraria. Dedica 624 cifre a ciascun numero e hai superato l'intervallo e la precisione del virgola mobile a precisione doppia.
Segna il

@phresnel (2) Buon punto. Ho aggiornato la mia risposta per assumere lo stesso numero di bit.
Evorlor

-2

Usa il modello Memento .

Nella corsa iniziale, salva i dati posizionali per ogni fotogramma o qualsiasi benchmark di cui hai bisogno. Se è troppo poco performante, fallo solo ogni n frame.

Quindi, quando riproduci la simulazione, segui la fisica arbitraria, ma aggiorna i dati posizionali ogni n frame.

Pseudo-codice eccessivamente semplificato:

function Update():
    if(firstRun) then (SaveData(frame, position));
    else if(reproducedRun) then (this.position = GetData(frame));

9
Non penso che questo funzioni per il caso di OP. Diciamo che io e te stiamo entrambi giocando su sistemi diversi. Ognuno di noi posiziona i pezzi del puzzle allo stesso modo, una soluzione che non è stata prevista in anticipo dallo sviluppatore. Quando fai clic su "start", il tuo PC simula la fisica in modo tale che la soluzione abbia successo. Quando faccio lo stesso, una piccola differenza nella simulazione porta alla mia (identica) soluzione non classificata come riuscita. Qui, non ho l'opportunità di consultare il ricordo della tua corsa di successo, perché è successo sulla tua macchina, non al momento dello sviluppo.
DMGregory

@DMGregory È corretto. Grazie.
jvn91173
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.