Superare i limiti del galleggiante per mondi di dimensioni planetarie in Unity


8

Per quanto ne so, andare oltre 1 milione di unità dall'origine mondiale in Unity è difficilmente possibile a causa di problemi di precisione in virgola mobile.

Rendere un mondo più di 1 milione di unità nel raggio richiederebbe l'uso di doublevar per le coordinate o l'utilizzo di una tecnica di divisione dello spazio per dividere una scena massiccia in blocchi gerarchici con il più piccolo di circa 10 000 unità, vale a dire che ogni posizione dello spazio mondiale sarebbe espressa dalla gerarchia del blocco in cui si trova l'oggetto e un gruppo di floatvariabili che rappresentano la sua posizione locale (e possibilmente rotazione e ridimensionamento) all'interno dell'ultimo blocco.

In entrambi i casi, ciò richiederebbe l'implementazione di un sistema di coordinate completamente nuovo, quindi mi piacerebbe sapere se ciò è possibile in Unity e, in tal caso, come posso farlo funzionare con i sistemi Unity esistenti come la fisica e così via.

PS Non posso semplicemente far muovere il mondo all'origine mentre il giocatore si muove poiché voglio che le cose accadano simultaneamente in tutto il pianeta.

Grazie!

Risposte:


5

Stai pensando in termini molto statici.

Solo perché un oggetto è a mezzo mondo di distanza non richiede alcun problema. Se le coordinate delle entità vengono memorizzate in relazione al blocco piuttosto che al mondo, ciò è banale da ottenere.Benvenuto nel modo in cui dovresti farlo se stessi scrivendo un mondo voxel in codice nativo.

Supponiamo quindi un concetto chiamato locales . È un insieme di pezzi che sono vicini l'uno all'altro. Ciò che conta è che lo spazio float interno a una determinata locale non superi mai il limite di sicurezza. Devi determinare quali sono le tue localizzazioni di elaborazione discrete, iniziare prendendo tutti i pezzi che rientrano in un raggio della posizione dell'entità n (potrebbe essere il giocatore o qualcos'altro). Nel mio motore attuale, mi assicuro che se anche una parte di due diverse localizzazioni si sovrappone, queste localizzazioni si uniscono in una locale / set di blocchi unici. Ciò garantisce che non si elaborino mai tutte le entità in un singolo blocco più di una volta, in un determinato frame.

Ora che hai le tue locales / chunk-sets, puoi eseguire la logica di gioco su di loro e sul loro contenuto. E non importa come lontano sono lontano dal giocatore o di origine. Ciò che conta è che ottieni un pezzo che è approssimativamente centrale per ogni set, floattrattalo come l'origine, cioè [0.0,0.0,0.0], e procedi verso l'esterno da lì. Vista la tipica distanza di visualizzazione in un gioco, ti garantisco che non avrai mai bisogno di vedere più di qualche chilometro, il che è molto fattibile float, senza problemi seri.

A parte Unity, un'opzione è scrivere un motore da zero, immagino, e usare qualcosa come libfixmath, dove puoi ancora usare i punti decimali ma poiché non galleggiano , non avranno mai questi problemi di precisione. Ma ti garantisco che avrai bisogno di pezzi e locali per altri motivi, quindi probabilmente non vale la pena.


Hai detto che non avrò mai bisogno di vedere più di qualche chilometro di distanza, ma che dire di un mondo di dimensioni planetarie, che dovrei essere in grado di osservare completamente dallo spazio (vedi outerra )?
Fa Maisak il

@MaksimMaisak La logica di gioco richiede precisione numerica; il rendering no. Non avrai mai bisogno di vedere il mondo dettagliato e preciso dallo spazio. C'è una certa altezza alla quale puoi passare dall'accurato sistema a terra che ho descritto sopra, alla meno precisa, prospettiva spaziale, senza soluzione di continuità (se giochi bene le tue carte). Ma tieni presente che c'è una differenza tra rendering e logica di gioco.
Ingegnere,

E come dividi lo spazio in blocchi? Inizi con pezzi e li raggruppi in locali o inizi con locali e li dividi in pezzi?
Fa Maisak il

Inizi con pezzi. "Locali" qui significa solo "quartieri di pezzi", quindi il concetto di pezzo è il prerequisito.
Ingegnere,

Come può un pezzo 'sovrapporsi' allora?
Fa Maisak il

6

Questa è una domanda che si presenta spesso. Mi prenderò la libertà di inoltrarti a un'altra risposta abbastanza dettagliata che ho già dato allo stesso problema, invece di ripeterlo qui: è possibile un sistema di coordinate personalizzato in Unity

Da lì, ciò che suggerirei di più è che leggi il fantastico documento su: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.471.7201&rep=rep1&type=pdf . Confronta alcuni dei modi per affrontare il problema che descrivi (comprese le coordinate locali, come descritto dall'ingegnere arcano nella sua risposta) e approfondire la soluzione di origine float di oggi. Il che è, in effetti, ciò che vorrei fare nella maggior parte dei casi (in realtà, è quello che sto usando nella mia applicazione).

Certo, hai detto che la soluzione float origin non soddisfa le tue esigenze. Ma questo potrebbe non essere il caso anche se vuoi che le cose continuino ad accadere in parti molto lontane del mondo. Puoi avere praticamente qualsiasi IA che accade ovunque tu voglia - non dovresti fare controlli di collisione o posizionamento preciso troppo lontano dal giocatore (cioè oltre la soglia di inesattezza del galleggiante). Tuttavia, francamente, nelle applicazioni reali probabilmente non saresti mai in grado di avere così tante collisioni e posizionamenti in un gioco a causa delle limitazioni di elaborazione. Eppure, potrebbero esserci soluzioni anche a quella limitazione che vedi sulla soluzione di origine float, a seconda delle caratteristiche del tuo gioco. Ancora una volta, ti suggerisco di non scartare quella soluzione prima di una lettura più approfondita al riguardo.

Tuttavia, se decidi che dovresti provare i sistemi di coordinate locali (che possono diventare una soluzione abbastanza complessa a seconda di dove vai con esso), allora il secondo elemento nella mia risposta collegata è per te. Il pezzo più importante è il documento scritto dal ragazzo che per primo ha implementato quella soluzione nel gioco pionieristico Dungeon Siege: http://scottbilas.com/files/2003/gdc_san_jose/continuous_world_paper.pdf

C'è anche un video di un paio d'anni fa, in cui le persone di Unity commentano quella soluzione e spiegano persino una moderna implementazione del concetto in Unity:

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

Spero che sia d'aiuto.


3

Non sono sicuro di aver già scelto una soluzione, ma vorrei menzionare altre due risorse che potrebbero essere utili a te e agli altri lettori in futuro.

  • Questo recente discorso di CppCon: "Demistificare il virgola mobile" , che è molto rilevante indipendentemente dal linguaggio di programmazione. Un punto molto interessante presentato sulla precisione è che il punto debole dell'accuratezza del galleggiante è compreso nell'intervallo [-1, + 1]. Quindi i galleggianti normalizzati sono il modo migliore per andare se puoi usarli.

  • Un altro posto in cui potresti voler cercare alcune idee è nel classico gioco Dungeon Siege . Il gioco utilizzava un sistema mondiale continuo basato su nodo / riquadro e ogni posizione era relativa al nodo corrente. In questo white paper c'è una descrizione molto dettagliata del sistema utilizzato dal gioco . Ho anche scritto alcuni paragrafi al riguardo nel mio blog . Questa configurazione era inedita all'epoca, ma probabilmente non è così utile oggi, il documento sopra citato menziona alcuni dei problemi che avevano. Tuttavia, è interessante da una prospettiva storica e potrebbe ancora servirti come fonte di idee e ispirazione.

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.