Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Ottimizzare le prestazioni della navigazione

../../_images/nav_optimization.webp

I problemi comuni relativi alle prestazioni di navigazione si possono categorizzare nei seguenti argomenti:

  • Problemi di prestazioni durante l'analisi dei nodi nell'albero di scene per la preparazione delle mesh di navigazione.

  • Problemi di prestazioni durante la preparazione delle mesh effettive di navigazione.

  • Problemi di prestazioni con le ricerche dei percorsi per gli agenti di navigazione.

  • Problemi di prestazioni con le ricerche effettive di percorsi.

  • Problemi di prestazioni con la sincronizzazione della mappa di navigazione.

Nelle sezioni seguenti è possibile trovare informazioni su come identificare, correggere, o almeno mitigare il loro impatto sui frame rate.

Problemi di prestazioni durante l'analisi dei nodi nell'albero di scene

Suggerimento

Preferisci usare forme semplici con il minor numero possibile di spigoli, ad esempio niente di arrotondato come un cerchio, una sfera o un toro.

Preferisci usare forme di collisione fisica invece di mesh visive complesse come geometria sorgente, poiché le mesh devono essere copiate dalla GPU e sono solitamente molto più dettagliate del necessario.

In generale, evita di utilizzare geometrie molto complesse come geometria sorgente per la preparazione delle mesh di navigazione. Ad esempio, non utilizzare mai una mesh visiva molto dettagliata; analizzare la sua forma in array di dati, e "voxelizzarla" per preparare le mesh di navigazione, richiederà molto tempo senza migliorare notevolmente la qualità della mesh di navigazione finale. Utilizza invece una versione molto più semplificata (LOD) di una forma. Ancora meglio, utilizza forme molto primitive come riquadri e rettangoli che coprono solo approssimativamente la stessa geometria ma producono comunque un risultato di preparazione abbastanza buono per il pathfinding.

Preferisco utilizzare semplici forme di collisione fisica rispetto alle mesh visive come geometria sorgente per la creazione delle mesh di navigazione. Le forme fisiche sono, di norma, molto limitate e ottimizzate, facili e veloci da analizzare. Una mesh visiva, d'altra parte, può variare da semplice a complessa. Inoltre, per accedere ai dati della mesh visiva, il parser deve richiedere gli array dei dati della mesh al RenderingServer, poiché i dati della mesh visiva sono memorizzati direttamente sulla GPU e non nella cache della CPU. Ciò richiede il blocco del thread del RenderingServer e può influire gravemente sul frame rate durante l'esecuzione, mentre il rendering è eseguito in più thread. Se il rendering è eseguito in un singolo thread, l'impatto sul frame rate potrebbe essere ancora peggiore e l'analisi della mesh potrebbe bloccare l'intero gioco per alcuni secondi su mesh complesse.

Problemi di prestazioni con la preparazione delle mesh di navigazione

Suggerimento

In fase di esecuzione, è sempre preferibile utilizzare un thread in background per la preparazione delle mesh di navigazione.

Aumenta cell_size e cell_height di NavigationMesh per creare meno voxel.

Cambia SamplePartitionType da watershed a monotone o layers per migliorare le prestazioni di preparazione.

Avvertimento

NON cambiare MAI la scala della geometria sorgente con i nodi per evitare errori di precisione. La maggiorità delle scale si applica solo visivamente e le forme molto grandi alla loro scala base richiedono comunque molta elaborazione in più, anche se rimpicciolite.

Se possibile, la preparazione delle mesh di navigazione in fase di esecuzione si dovrebbe sempre eseguire in un thread in background. Anche le mesh di navigazione di piccole dimensioni possono richiedere molto più tempo di quanto sia possibile stringere in un singolo frame, assumendo che il frame rate debba rimanere a un livello tollerabile.

La complessità dei dati della geometria sorgente analizzati dai nodi dell'albero di scene ha un impatto significativo sulle prestazioni di preparazione, poiché tutto deve essere mappato su una griglia/voxel. Per le prestazioni di preparazione in fase di esecuzione, la dimensione e l'altezza delle celle di un NavigationMesh si devono impostare il più alte possibile, senza causare problemi di qualità della mesh per un gioco. Se la dimensione o l'altezza delle celle sono impostate troppo basse, la preparazione è costretta a creare una quantità eccessiva di voxel per elaborare la geometria sorgente. Se la geometria sorgente si estende su un mondo molto ampio di gioco, è persino possibile che il processo di preparazione esaurisca la memoria nel mezzo e provochi un arresto anomalo. Anche il tipo di partizione si può ridurre a seconda della complessità della geometria sorgente per ottenere prestazioni migliori. Ad esempio, i giochi con superfici prevalentemente piatte e geometria a blocchi possono utilizzare la modalità monotona o a strati, che sono molto più veloci da preparare (ad esempio perché non richiedono passaggi di campo a distanza).

Non cambiare mai la scala della geometria sorgente con i nodi. Non solo può causare molti errori di precisione con vertici e spigoli non corrispondenti correttamente, ma alcuni cambiamenti sono presenti solo come elementi visivi e non nei dati effettivamente analizzati. Ad esempio, se una mesh viene rimpicciolita visivamente nell'Editor, ad esempio impostando la scala a 0,001 su una MeshInstance, per la preparazione la mesh richiede comunque di elaborare una griglia voxel gigantesca e molto complessa.

Problemi di prestazioni con le ricerche di percorsi degli agenti di navigazione

Suggerimento

Evita inutili ripristini del percorso e richieste a ogni frame negli script degli agenti di navigazione.

Evitare di aggiornare tutti i percorsi degli agenti di navigazione nello stesso frame.

Errori logici e operazioni inutili negli script personalizzati degli agenti sono cause molto comuni di problemi di prestazioni, ad esempio presta attenzione se il percorso è ripristinato a ogni singolo frame. Normalmente, gli agenti di navigazione sono ottimizzati per richiedere nuovi percorsi solo quando la posizione di destinazione cambia, la mappa di navigazione cambia o vengono forzati a una distanza troppo lontana dal percorso desiderato.

Ad esempio, quando l'IA deve spostarsi verso il giocatore, la posizione di destinazione non si dovrebbe impostare sulla posizione del giocatore a ogni singolo frame, poiché ciò richiede un nuovo percorso a ogni frame. Invece, la distanza tra la posizione di destinazione attuale e la posizione del giocatore si dovrebbe confrontare, e solo quando il giocatore si è spostato troppo lontano si dovrebbe impostare una nuova posizione di destinazione.

Non verificare in anticipo se una posizione di destinazione è raggiungibile a ogni frame. Ciò che sembra una verifica innocua è equivalente a una costosa ricerca di percorso dietro le quinte. Se si prevede di richiedere comunque un nuovo percorso nel caso in cui la posizione sia raggiungibile, si dovrebbe richiedere direttamente un percorso. Esaminando l'ultima posizione del percorso restituito e se tale posizione si trova a una distanza "raggiungibile" dalla posizione verificata, si risponde alla domanda "questa posizione è raggiungibile?". Ciò evita di eseguire l'equivalente di due ricerche di percorso complete a ogni frame per lo stesso agente.

Dividi il numero totale di agenti di navigazione in gruppi di aggiornamento oppure utilizza timer casuali, in modo che non richiedano tutti nuovi percorsi nello stesso frame.

Problemi di prestazioni con la sincronizzazione della mappa di navigazione

Suggerimento

Unisci i poligoni delle mesh di navigazione per vertice anziché per connessioni tra bordi, ove possibile.

Quando vengono apportate modifiche, ad esempio, alle mesh di navigazione o alle regioni di navigazione, il NavigationServer deve sincronizzare la mappa di navigazione. A seconda della complessità delle mesh di navigazione, ciò può richiedere molto tempo, il che potrebbe avere un impatto sul frame rate.

Il NavigationServer unisce le mesh di navigazione per vertice o per connessione di spigolo. L'unione per vertice avviene quando i due vertici di due spigoli diversi si trovano nelle stesse celle della griglia della mappa. È un'operazione piuttosto rapida e a basso costo. L'unione per connessione di spigolo avviene in un secondo passaggio per tutti gli spigoli non ancora uniti. Tutti gli spigoli liberi sono verificati per possibili connessioni di spigolo in base sia alla distanza sia all'angolo, il che è piuttosto costoso.

Quindi, oltre alla regola generale di avere il minor numero possibile di spigoli poligonali, il maggior numero possibile di spigoli dovrebbe essere unito per vertice in anticipo, in modo che solo pochi spigoli siano lasciati per il calcolo più costoso della connessione degli spigoli. Il PerformanceMonitor di debug per la navigazione si può utilizzare per ottenere statistiche su quanti poligoni e spigoli sono disponibili e quanti di essi non sono uniti o non uniti per vertice. Se il rapporto tra vertici uniti e connessioni degli spigoli è molto diverso (per i vertici dovrebbe essere notevolmente più alto), le mesh di navigazione vengono create correttamente o posizionate molto inefficientemente.