Tempo di caricamento pre-partita vs. tempo di caricamento nel gioco


9

Sto sviluppando un gioco in cui è incluso un labirinto casuale .
Ci sono alcune creature dell'IA che si nascondono nel labirinto. E voglio che seguano un percorso secondo la forma dei labirinti.

Ora ci sono due possibilità per me di implementarlo, il primo modo (che ho usato) è calcolare diversi percorsi in agguato una volta creato il labirinto.
Il secondo è calcolando un percorso che una volta doveva essere calcolato, quando una creatura inizia a nasconderlo.

La mia principale preoccupazione sono i tempi di caricamento. Se calcolo molti percorsi durante la creazione del labirinto, il tempo di pre-caricamento è un po 'lungo, quindi ho pensato di calcolarli quando necessario.
Al momento il gioco non è "pesante", quindi non è evidente calcolare i percorsi a metà partita, ma temo che una volta diventerà più complicato.

Eventuali suggerimenti, commenti, opinioni, saranno di aiuto.

Modificare:

Per ora, psia il numero di percorsi pre-calcolati, una creatura ha la probabilità di 1/pprendere un nuovo percorso (che significa un calcolo del percorso) anziché uno esistente.
Una creatura non inizia la sua pattuglia fino a quando il percorso non è completamente calcolato, quindi non c'è bisogno di preoccuparsi che venga ucciso nel processo.


8
A questo punto, sarebbe pre-ottimizzazione. Lascerei così com'è fino a quando non c'è un problema.
John McDonald

3
E per suonare un po 'con @JohnMcDonald, se riesci a calcolare questi percorsi a metà partita e non è evidente, quanto di un fattore che contribuisce possono essere al momento del caricamento?
James

Risposte:


6

BerickCook ha espresso correttamente l'idea. Lascia i calcoli dove sono se funzionano correttamente ora.

Se puoi fare il calcolo prima e sei sicuro di non averne bisogno a metà partita, allora fallo prima. Altrimenti fallo dopo il caricamento. Se il calcolo durante il gioco è impercettibile, puoi farlo lì. Se a un certo punto la complessità si evolve e i calcoli diventano troppo pesanti, inizia l'ottimizzazione.

Ma una cosa: se i tuoi calcoli sono implementati per l'esecuzione a metà partita, puoi sempre forzarli ad eseguirli durante il caricamento.

Esistono numerose soluzioni:

  • calcola / carica i percorsi durante la creazione / caricamento del livello
  • utilizzare un secondo thread per calcolare i percorsi
  • ottimizza i tuoi algoritmi
  • utilizzare un sistema interrompibile se non si ha accesso al threading.

Ho visto e usato l'ultima opzione in un gioco del mercato di massa. Assicurati semplicemente di salvare correttamente tutti i dati necessari per riprendere il calcolo e controllare regolarmente il tempo / le operazioni rimanenti durante il calcolo.

A seconda del caso, il sistema interrompibile potrebbe fornire soluzioni preliminari e parziali che possono essere utilizzate evento prima della fine del calcolo.


Modifica : risposta a @Keeper

L '"algoritmo interrompibile" è stato utile solo a causa dei vincoli che avevamo. Fondamentalmente ci siamo indeboliti dalla mancanza di multithreading.

A un certo punto abbiamo avuto un gioco in cui l'IA ha dovuto calcolare grandi quantità di mosse basate su più dizionari. Durante questo calcolo tutte le animazioni si fermavano perché i dizionari venivano espansi con più dati e il set di dati contenente i dati veniva modificato e meno efficiente quando il gioco veniva adattato per il multiplayer (dove l'IA doveva interagire anche per le mosse del giocatore). Avevamo un solo thread disponibile per il loop del gioco (l'imperativo è che il codice multi-piattaforma deve essere eseguito su tutte le piattaforme supportate). A questo punto è stato deciso di interrompere l'algoritmo di calcolo in modo da poterlo interrompere. Pertanto non potevamo semplicemente usare il sistema ricorsivo che era in atto poiché le variabili non potevano essere salvate. Le funzioni sono state sostituite con oggetti che contenevano semplicemente tutte le variabili e i puntatori necessari per gli oggetti padre e figlio. Io non

  • salva lo stato dei suoi calcoli correnti
  • interrompere alla fine di un ciclo o durante un ciclo (quando un oggetto figlio interrompe)
  • esci quando il tempo è scaduto
  • riprendere da dove ha interrotto il riavvio di un ciclo nell'indice giusto o la chiamata dell'oggetto figlio che si trova attualmente nella parte superiore dello stack figlio.
  • pulire tutto se il calcolo viene interrotto
  • dare il miglior risultato parziale.

Solo le operazioni più costose sono state suddivise in oggetti separati e ci è voluto del tempo per trovare i posti giusti in cui potevamo interrompere i calcoli, ma alla fine funziona molto bene.

Abbiamo perso le prestazioni, ma le prestazioni percepite erano molto migliori per l'utente poiché le animazioni funzionavano senza problemi su tutte le piattaforme, tutte le piattaforme potevano quindi utilizzare i dizionari più grandi senza soffrire di animazioni discordanti o blocchi. Anche questo ci ha permesso di eseguire più istanze in parallelo quando ne avevamo bisogno in seguito.

Ovviamente ora su iPhone e iPad il gioco non ha bisogno di questo, usare un secondo thread sarebbe l'ideale. Ma sospetto che il codice sia ancora lì.


Grazie, sembra molto interessante. Potete per favore approfondire il concetto di "sistema interrompibile" (perché e come). (googling non è stato così utile ..). Aggiungerò alcuni dettagli alla domanda.
Custode

@Keeper Spero di aver risposto alla tua domanda sulla parte interrompibile. È una seccatura da fare e non è rilevante sulla maggior parte dei sistemi moderni.
Coyote,

Anche se per ora non userò questo metodo, mi hai aperto gli occhi su qualcosa di nuovo. La tua risposta merita di essere accettata.
Custode

8

Per ora, poiché calcolare i percorsi a metà partita è impercettibile, questo è l'approccio ideale. Se / quando arriva al punto in cui il gioco viene interrotto dai calcoli, passa a per calcolare i percorsi prima che il livello venga caricato.

Tempi di caricamento iniziali più lunghi sono perdonabili, ma generalmente le fluttuazioni di FPS casuali durante il gioco non lo sono.


2

Una possibilità, se necessario, è quella di spostare i calcoli su un secondo thread poiché quasi tutti i PC hanno più di un core CPU al giorno d'oggi.

Il processo di base sarebbe:

  • Quando una creatura richiede un percorso, aggiungi la richiesta a una coda di richieste thread-safe e segnala il thread.
  • La creatura rimane inattiva mentre attende che il thread salti la voce da quella coda, la elabori e la metta in un elenco completo.
  • Ogni fotogramma controlla l'elenco completo dal thread principale e assegna percorsi completi alle creature.

Devi fare attenzione anche ad alcuni casi limite (ad esempio, se la creatura muore prima che la richiesta venga elaborata).


2
Se non si desidera introdurre il threading, è anche possibile calcolare il percorso in modo incrementale (ad es. Calcolare alcuni passaggi ogni frame).
Bummzack
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.