Perché dovrei sempre considerare la creazione e l'utilizzo di pool di oggetti invece di creare un'istanza al volo del nuovo oggetto?


25

Ho letto di questo modello più volte (dal punto di vista delle migliori pratiche):

Allocazione della memoria : invece di creare istanze al volo del nuovo oggetto, prendere sempre in considerazione la creazione e l'utilizzo di pool di oggetti. Aiuterà a ridurre la frammentazione della memoria e a far funzionare meno il Garbage Collector.

Tuttavia, non so cosa significhi effettivamente. Come posso implementarlo?

Ad esempio, posso creare un'istanza GameObjectutilizzando il Instantiatemetodo di Unity?

Instantiate(prefab, new Vector3(2.0F, 0, 0), Quaternion.identity);

Questo uso è scoraggiato? Cos'altro può significare?



Grazie Hellium non ho visto il video (troppo grande) ma il testo mi aiuta davvero a capire "L'atto di istanziare e distruggere è inefficiente e può rallentare i tuoi progetti"
Muhammad Faizan Khan,

1
Nota che, sebbene questo consiglio sia comune, non è un requisito assoluto per ogni gioco. Soprattutto se stai realizzando un gioco desktop piccolo / corto, invio di jam o prototipo, non devi fare di tutto per implementare il pool. Nei miei test di immersione, Unity è in grado di sopportare persino la generazione e la distruzione massiccia meglio di quanto gli diamo credito. ;) Ma considera il pooling se stai realizzando un gioco lungo in cui non vuoi che i rifiuti si accumulino e causino una balbuzie quando vengono raccolti in seguito, o se stai prendendo di mira piattaforme mobili in cui l'impatto sulle prestazioni è sentito più acutamente.
DMGregory

Grazie @DMGregory Hai ragione. il tuo input è sempre prezioso. Non dovremmo preoccuparci del pooling di oggetti in piccoli giochi in quanto richiederà un ulteriore lavoro di codifica.
Muhammad Faizan Khan,

1
Questo è un modello molto comune, ma assicurati di temperarlo con la regola: "Profili prima, poi ottimizza". È facile ottimizzare le cose che non contano.
Cort Ammon - Ripristina Monica il

Risposte:


41

Se stai pianificando di creare un'istanza di molte istanze dello stesso prefabbricato, dovresti assolutamente pensare all'utilizzo del pool di oggetti. La chiamata alla funzione di istanza di Unity è una delle chiamate al metodo più faticoso che potresti effettuare.

Il pooling di oggetti avviene quando si istanziano prefabbricati prima che vengano utilizzati. Sono disattivati ​​immediatamente all'istanza e riattivati ​​solo quando sono necessari. Mentre questo aumenta l'utilizzo della memoria, evita il sovraccarico della CPU di istanziare durante il gioco.

Ad esempio, sto attualmente lavorando a un gioco infernale che richiede la generazione di centinaia di proiettili in fase di esecuzione. Inizialmente ho provato a creare il gioco senza un pool di oggetti, ma alla fine è stato un disastro (meno di 2 fps). Ora, unisco 500 pallottole prima dell'inizio del gioco e il gioco è incredibilmente veloce (200 fps).

Ci sono situazioni in cui il pool di oggetti non può essere utilizzato. Ad esempio, se hai un gioco in cui l'input del giocatore determina quale prefabbricato viene generato, allora potresti non avere altra scelta che usare la normale chiamata di Instantiate. Il pooling di oggetti è possibile solo quando si conosce in anticipo quali oggetti saranno necessari.

Il tutorial di Sebastian Lague su YouTube è un'ottima risorsa per apprendere il pool di oggetti: https://youtu.be/LhqP3EghQ-Q


"L'atto di istanziare e distruggere sono inefficienti e possono rallentare i tuoi progetti". questo è il motivo? Quindi significa che dobbiamo programmare un po 'di più (come attivare la disattivazione o impostare di nuovo la posizione del proiettile in modo da poter sparare di nuovo)
Muhammad Faizan Khan,

12
Potrebbe valere la pena menzionare l'allocazione e la raccolta dei rifiuti come importanti fattori che contribuiscono al costo della ripetuta istanza e distruzione. Genera abbastanza spazzatura e alla fine l'intero gioco deve aspettare che il cestino della spazzatura lo spazzi via. ;)
DMGregory

3
@corsiKa sarebbe un'ottimizzazione dell'era degli anni '80. Unity può semplicemente disattivare i prefabbricati in questione, facendo ignorare i suoi sistemi.
congusbongus,

2
"Ad esempio, se hai un gioco in cui l'input del giocatore determina quale prefabbricato viene generato, allora potresti non avere altra scelta che usare la normale chiamata di Instantiate." - Non proprio. È possibile disporre facilmente di più pool di oggetti per diversi prefabbricati allocati alle dimensioni desiderate all'avvio (o al caricamento della scena). Oppure, se si volesse realizzarlo, potrebbe funzionare anche un pool di oggetti che memorizza più tipi prefabbricati.
Ethan Bierlein,

1
@DMGregory In un tipico ambiente GC, la disallocazione è la maggior parte dei costi; in un tipico ambiente non GC, l'allocazione è la maggior parte dei costi. Il pooling di oggetti funziona alla grande per entrambi, in realtà sono solo due facce della stessa medaglia. In casi estremi, i vecchi giochi venivano scritti con tutti gli oggetti "allocati" fin dall'inizio - una de / allocazione della memoria molto scarsa o assente mentre il gioco era in esecuzione. Non hai davvero usato nulla che non sia stato "raggruppato" in qualche modo. Poiché Unity utilizza molti "metadati" in tempo reale, il pooling può essere di grande aiuto, anche se può anche essere più complicato da implementare.
Luaan,
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.