In che modo Dwarf Fortress tiene traccia di così tante entità senza perdere le prestazioni?


79

In Dwarf Fortress puoi avere in gioco centinaia di Nani, animali, folletti, ecc. In qualsiasi momento, ognuno con la propria complessa IA e routine di pathfinding. La mia domanda è come questo non produce un notevole rallentamento? Ogni Nano corre nel suo thread?


6
Domanda interessante. Anche se non mi piace il modo in cui è formulato, dal momento che sarebbe solo una speculazione rispondere a questa domanda come formulata. Ad ogni modo, potresti aver visto questo articolo parlare con Tarn Adams. Dove coprono brevemente il percorso.
MichaelHouse

25
E ' assolutamente produce rallentamento evidente una volta che hai una topologia tunnel complessa e 100 + nani.
Russell Borogove,

3
Sì, DF nella mia esperienza è incredibilmente lento nello scenario che descrivi.
Argentage,

4
Distruggi una tromba delle scale principale e osserva il tuo framerate cadere come una roccia per un momento mentre ogni nano si rimette improvvisamente nello stesso momento.
Mooing Duck,

2
Ho intenzione di entrare e concordare sul fatto che DF non è il miglior esempio; infatti DF è noto per avere problemi di prestazioni.
Robert S.,

Risposte:


110

Qualsiasi sistema che avesse un thread per ognuno di così tanti personaggi avrebbe esaurito le risorse molto rapidamente. I thread possono darti accesso a core di processore extra, ma non rendono nulla intrinsecamente più efficiente e vengono forniti con un overhead.

La semplice risposta è solo quella di essere efficiente nell'elaborare ogni entità nel gioco.

  • Non elaborare ogni entità per ogni frame.
  • Dividi l'elaborazione in cose che devono essere fatte spesso e cose che non hanno bisogno di fare spesso.
  • Distribuire algoritmi di lunga durata su più frame in modo che non blocchino l'elaborazione in altri sistemi.
  • Garantire che vengano utilizzati algoritmi e strutture dati efficienti.
  • Memorizza nella cache i risultati di calcoli costosi se è probabile che vengano riutilizzati.

2
+1 per questo, per aver effettivamente spiegato cosa sta succedendo, piuttosto che perdere tempo con la grafica come me. :)
Matt Kemp,

4
Per essere onesti, ti ho dato anche +1 perché mi sono dimenticato di quell'aspetto, ed è molto vero: togli gfx dall'equazione ed è come rendere i computer 2x o 3x più veloci all'istante.
Kylotan,

Ho sentito che DF ora è multithread, ma almeno fino a poco tempo fa, è stato fatto tutto in un singolo thread. (Potrebbe essere ancora, non ne sono sicuro)
Mooing Duck il

@MooingDuck Non lo è ancora.
Tharwen,

63

Dwarf Fortress non è open source, e mentre ci sono molte congetture e ingegneria inversa che possono andare su come tutto funzioni, mi concentrerò invece su alcune tecniche di base per ottimizzare un roguelike 3D (non grafica 3D, mondo 3D) del stesso tipo.

Come in tutti i videogiochi, ci sono molti fumi e specchi che creano l'illusione della complessità da semplici regole e sistemi. Questi vanno dall'uso di semplici numeri casuali per movimenti senza scopo fino alla pre-cottura di una maglia di nodi di alto livello per l'individuazione del percorso.

Movimento

Parlando di pathfinding, questo può spesso essere un problema molto difficile da risolvere per grandi spazi come può essere una mappa DF (fino a 768x768x64 IIRC), tuttavia il problema può essere semplificato e accelerato in questi modi:

  • Rete di nodi precotta: quando viene creata la mappa, il mondo può essere suddiviso in blocchi e ogni blocco può essere mappato per le sue uscite e entrate. Quando viene aggiornato un blocco, ad esempio quando viene costruito un muro, è necessario aggiornare solo la rete di quel blocco.
  • Path stinding: l'esecuzione di un percorso sull'intera mappa, cella per cella, richiederebbe molto tempo, invece il percorso su una rete di blocchi più grande, che mappa tutte le connessioni tra blocchi, quindi esegue un percorso all'interno del blocco solo quando passando da un pezzo all'altro. Questo fa 2 cose per te. Accelera l'individuazione del percorso suddividendolo su molti pezzi più piccoli e consente inoltre all'unità di cambiare direzione a metà del percorso quando un pezzo si aggiorna. Ripercorrerebbe il percorso attraverso la rete di grandi dimensioni se uno dei nodi necessari per l'aggiornamento incrociato.
  • Sterzo casuale: quando non ci si sposta verso un obiettivo, l'unità deve solo camminare senza meta. Molti roguelike muovono semplicemente l'unità in una direzione casuale, che sembra innaturale. Possono essere utilizzate varie tecniche di sterzo, quelle semplici stanno favorendo lo spostamento in linea retta e hanno sempre meno possibilità di spostarsi nelle direzioni che si irradiano verso la parte posteriore, il che avrebbe solo una probabilità dell'1% circa. Quindi l'unità a volte inverte completamente la direzione, ma solo raramente.

Non tratterò le basi del pathfinding. La maggior parte dei roguelike usa A *, ma ci sono altri metodi per scuoiare il gatto. Mmmm Cat leather ..

Compiti personali

Una delle cose principali che fa apparire e sentire in vita le unità DF è il loro elenco di obiettivi personali. In verità molti giochi roguelike hanno questo a un livello base. Essenzialmente ogni unità ha un elenco di desideri (e per i tuoi dorf, compiti che potrebbero raccogliere che stai chiedendo di fare) e sceglieranno da loro in base alla loro personalità (statistiche).

Alcune attività hanno dei requisiti. Realizzare una gonna di pelle richiede che il Dorf si trovi in ​​un negozio del genere con articoli X. Quindi quelli tutti vengono controllati e aggiunti come attività al loro elenco. Semplice come quella.

Poiché la maggior parte delle volte un'unità sarà in transito, i controlli su ciò che le unità stanno facendo possono essere molto veloci, solo poche unità faranno una scelta in un dato momento, quindi nel complesso non c'è rallentamento nemmeno per centinaia o migliaia di unità. E ricorda, in DF tutto è dalle api ai trogloditi agli alberi.


Nel fare qualche ricerca aggiuntiva è chiaro che, esilarante, DF sta facendo un terribile lavoro di ricerca di percorsi in generale. Non sta suddividendo la mappa in blocchi, ma sta suddividendo la mappa in segmenti o aree collegate (che è meglio di niente di sicuro), quindi la mia valutazione sopra è ancora meno un esempio di come DF funziona. :) Il che non significa che DF sia niente di meno che sorprendente per un milione di altre ragioni.

Ciò dimostra che ciò che è importante in un gioco è il gioco. Non grafica, non programmazione eccezionale, scrittura eccezionale, musica eccezionale, nemmeno l'interfaccia; nient'altro è nemmeno dell'1% importante quanto il gioco stesso.


1
1024X1024X32? Verticale è 128 o 256 credo. È molto più grande di 32.
Lawton

@Lawton Credo di non essere corretto riguardo alla dimensione massima, ma l'altezza non è così errata. Lo sto correggendo. Ho caricato il gioco e l'imbarco su cui mi trovo è solo di circa 45 livelli. Altri potrebbero essere "simulati" ma non ho accesso ad essi per scavare o costruire.
DampeS8N,

@ DampeS8N Ho appena caricato una mappa media non muta e sono stato in grado di visualizzare da +16 a -156, circa 180 livelli. Le mappe a 40 livelli sono l'eccezione, non la regola. Anche se sei in grado di scavare solo 40 di loro a causa del blocco di una falda acquifera o di lava, non è rilevante, perché l'area sottostante è ancora popolata da un divertimento simulato.
Lawton,

@Lawton, la mia mappa mi permette di sfogliare solo 45 livelli. Sono assolutamente variabili ma non sono stato in grado di trovare facilmente i numeri su quante mappe sono accessibili. Può anche dipendere dalla versione del gioco che stiamo usando. Alla fine non è poi così importante per la mia risposta.
DampeS8N,

È un vecchio post ma le profondità nella fortezza nana dipendono da strati sedimentari. Come se la crosta terrestre fosse più spessa in alcuni punti. DF non è completamente geologico corretto, ma l'uomo lo studia come un professionista: D.
Madmenyo,

50

Da questa pagina :

Bene [il pathfinding] sembra fantastico dalla mia parte, dal momento che ci sono un sacco di personaggi che lo fanno tutti in una volta.

TA: I nani stessi si muovono per lo più con A *, con l'euristica vecchia strada a distanza. La parte difficile è che non può davvero chiamare A * se non sanno che possono arrivarci in anticipo, o finirà per inondare la mappa e uccidere il processore.

Non so se questo è sicuramente il modo in cui impedisce di "inondare la mappa" , ma il solito modo di farlo nei giochi è usare un'alterazione di A * chiamata Percorso gerarchico-Trovare A * o HPA *. L'idea è quella di spezzare la griglia in molti meno ma più grandi blocchi, quindi utilizzare A * per trovare il percorso migliore da ciascun blocco ai blocchi vicini. Puoi usarlo per costruire un grafico molto più piccolo su cui eseguire A * per ogni unità.

Pathfinding gerarchico

Puoi anche raggruppare quei pezzi in pezzi ancora più grandi, da dove proviene il "gerarchico".

Questo algoritmo trova solo percorsi quasi ottimali, ma per giochi come Dwarf-Fortress che di solito va bene. È ancora garantito di trovare un percorso se ne esiste uno; e quando non c'è percorso, riempirà solo il grafico più piccolo, risparmiando un enorme tempo.

Esiste anche un'astrazione dell'HPA * che si occupa di unità che possono andare su alcuni terreni ma non su altri (come le scogliere, su cui le unità aeree possono attraversare ma le unità di terra no) . Si chiama HAA * e c'è un articolo molto accessibile che lo spiega qui .

Puoi leggere di più sui vari algoritmi di pathfinding qui .


3
Ho trovato questo video dello sviluppatore RimWorld molto illuminante. È un gioco simile, mentre solo in 2D. Spiega le basi alla base del pathfinding e i vantaggi della separazione della mappa in regioni. youtube.com/watch?v=RMBQn_sg7DA
Sire

18

Semmai, è il contrario: l'intera cosa gira su un thread e ora sta colpendo il punto in cui questo sta diventando il fattore di blocco (l'ultima volta che ho controllato!)

Il motivo per cui è veloce è che non esiste una grafica sofisticata. È ingannevole, ma la cosa principale che rallenta le cose è disegnare cose (pensa ai due terzi di un fotogramma nei titoli AAA). Poiché la fortezza nana è piuttosto semplice, dedica il resto di quel tempo a fare cose interessanti.


8
Un punto a favore di questo è la riscrittura di OpenGL di qualche tempo fa che ricordo che ha portato un enorme aumento della frequenza dei fotogrammi. Quindi, anche facendo la semplice grafica sprite, DF ha avuto un impatto efficace.
millimoose,

3
+1 grafica a strisce = enorme quantità di tempo libero per l'elaborazione del gameplay
Laurent Couvidou,

2
Vale la pena notare che la grafica di DF è impegnativa quanto qualsiasi gioco 2D indipendente moderno. Esistono molte trame, anche se piccole e semplici, e possono essere distribuite su monitor full HD di proprietà immobiliari. Non ci sono effetti particellari appariscenti o quello che hai, ma il lavoro grezzo "dipingi tutti questi pixel" è ancora presente e, a causa del numero di chiamate di disegno necessarie per le dimensioni minuscole delle tessere, in realtà è una sfida piuttosto grande per rendere performanti.
DampeS8N,

All'inizio può sembrare una risposta sciocca, ma questo è corretto, immagina cosa si può fare con 4-12gb grammi e 4-12tflop di potenza GPU se non è necessario disegnare primitive complesse, scartare, trame, trasformare vettori 3d in un array di pixel 2D, shader, ecc.
Felype,

10

Non so come sia codificato DF, ma la quantità di AI non mi impressiona davvero perché ciò che le persone spesso lo sovrintendono al fatto che l' IA non ha bisogno di precisione . È perfettamente fattibile fare la maggior parte delle cose solo ogni pochi secondi. È anche possibile utilizzare calcoli imprecisi. L'imperfezione risparmia molte prestazioni . Puoi eseguire la routine decisionale di 100 unità ogni 100 ms, oppure puoi eseguirla per 1000 unità al secondo, ci vorrà la stessa quantità di tempo della CPU ma bene ... hai 10 volte le unità.

Ecco un semplice esempio di come si potrebbero gestire molte unità:

int curUnit;
Array<Unit> units;
[...]
while([...]) // Game Loop
{
  [...game logic...]
  // process 10 AIs per Frame
  for(int i=0; i++; i<10)
  {
    curUnit++
    if(curUnit == units.length()) curUnit=0;
    if(curUnit < units.length())
      units[curUnit].processAI();
  }

  // Update the position of all units, this should be as optimized as possible
  foreach(Unit& unit in units){ unit.move(); };

  [...graphics...]
}

L'intelligenza artificiale diventerà sempre meno reattiva quanto più ci sono, ma il giocatore probabilmente lo noterà solo in casi estremi.


C'è molto da dire su come passare attraverso pile di compiti che non sono precisi a livello di frame. I giochi AAA spesso impostano in modo esplicito ogni singolo reparto in percentuali di frame in modo che un reparto non possa calpestare le dita degli altri reparti. Se il metodo per animare l'oscillazione dell'albero in base alla velocità e alla direzione del vento è lento, verranno elaborati meno alberi anziché consumare il budget di altre squadre.
DampeS8N,
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.