Come funziona il pooling in Unity

banner

In Unity, esistono funzioni come Instantiate e Destroy per creare e distruggere gli oggetti nel gioco. Tuttavia, queste operazioni possono essere costose, specialmente se vengono eseguite molto spesso durante il gameplay. Immagina di star giocando a uno sparatutto, dove continuamente tutti i giocatori sparano contro altri nemici infiniti proiettili… sarebbe un continuo “Instantiate’n’Destroy”!

In situazioni del genere, dove bisogna creare e distruggere frequentemente oggetti, soprattutto quando si tratta dello sviluppo di videogiochi e la gestione delle risorse è fondamentale, si usa l’algoritmo di pooling.

Il pooling (da pool, “piscina di oggetti”) viene utilizzato quando vi è la necessità di gestire diversi oggetti che sono sempre gli stessi. In fase di inizializzazione dell’applicazione, l’algoritmo genera un certo numero di oggetti, che vengono attivati e disattivati quando necessario, utilizzando sempre le stesse risorse.

Implementazione del pooling

Creiamo la classe ObjectPoolingManager per gestire il pool di oggetti. Dapprima, viene istanziato un numero predefinito di oggetti e riutilizzati quando necessario. Il metodo GetPooledObject restituisce un oggetto disattivato nel pool quando richiesto.

public class ObjectPoolingManager : MonoBehaviour
{
    // Dichiarazione di variabili pubbliche
    public static ObjectPoolingManager instance; // Riferimento statico a se stesso per l'accesso globale
    public GameObject pooledObject; // Il tipo di oggetto da poolare
    public int pooledAmount = 10; // Il numero iniziale di oggetti da poolare

    // Lista di oggetti poolati
    private List<GameObject> pooledObjects;

    // Metodo chiamato quando l'oggetto viene inizializzato
    private void Awake()
    {
        // Verifica se c'è già un'istanza di ObjectPoolingManager
        if (instance == null)
            instance = this; // Se non c'è, imposta questa istanza come l'istanza singleton
        else
            Destroy(gameObject); // Se c'è già un'istanza, distruggi questo oggetto per evitare duplicati
    }

    // Metodo chiamato all'avvio
    void Start()
    {
        pooledObjects = new List<GameObject>(); // Inizializza la lista di oggetti poolati
        // Loop per creare e inizializzare gli oggetti poolati
        for (int i = 0; i < pooledAmount; i++)
        {
            GameObject obj = Instantiate(pooledObject); // Crea un nuovo oggetto dal prefab specificato
            obj.SetActive(false); // Disattiva l'oggetto appena creato
            pooledObjects.Add(obj); // Aggiunge l'oggetto alla lista di oggetti poolati
        }
    }

    // Metodo per ottenere un oggetto poolato disponibile
    public GameObject GetPooledObject()
    {
        // Loop attraverso gli oggetti poolati
        for (int i = 0; i < pooledObjects.Count; i++)
        {
            // Verifica se l'oggetto non è attivo nell'attuale gerarchia
            if (!pooledObjects[i].activeInHierarchy)
            {
                return pooledObjects[i]; // Se trovato, restituisci l'oggetto
            }
        }
        return null; // Se non ci sono oggetti disponibili, restituisci null
    }
}

Utilizzo del pooling

Vediamo ora come sfruttare il pooling manager per “spawnare1 oggetti ogni volta che vogliamo:

public class ObjectSpawner : MonoBehaviour
{
    public float spawnRate = 1f; // Frequenza di spawn degli oggetti
    public float despawnTime = 5f; // Tempo prima che gli oggetti spawnati vengano disattivati

    void Start()
    {
        StartCoroutine(SpawnObjects()); // Avvia la coroutine per lo spawn degli oggetti
    }

    // Coroutine per lo spawn degli oggetti
    IEnumerator SpawnObjects()
    {
        while (true) // Loop infinito per continuare lo spawn degli oggetti
        {
            yield return new WaitForSeconds(spawnRate); // Attendere per la durata della frequenza di spawn
            GameObject obj = ObjectPoolingManager.instance.GetPooledObject(); // Ottiene il primo oggetto disponibile (non ancora attivato) dal pooling

            if (obj != null) // Se è stato ottenuto un oggetto valido
            {
                obj.transform.position = transform.position; // Imposta la posizione dell'oggetto sulla posizione dello spawn
                obj.SetActive(true); // Attiva l'oggetto
                StartCoroutine(DeactivateObject(obj)); // Avvia la coroutine per disattivare l'oggetto dopo un certo periodo di tempo
            }
        }
    }

    // Coroutine per disattivare un oggetto dopo un certo periodo di tempo
    IEnumerator DeactivateObject(GameObject obj)
    {
        yield return new WaitForSeconds(despawnTime); // Attendere per il tempo di disattivazione
        obj.SetActive(false); // Disattiva l'oggetto
    }
}

In sintesi, l’algoritmo di pooling permette di:

  1. ridurre l’utilizzo della memoria: evita il “Instantiate’n’Destroy” continuo di oggetti in gioco, risparmiando risorse di memoria;
  2. migliorare le prestazioni e la stabilità: elimina il ritardo causato dalla creazione dinamica degli oggetti durante il gioco.

Pooling Esempio di Pooling in Unity


  1. Quando si parla di “spawnare” un oggetto in un gioco, si intende il processo di istanziazione di quell’oggetto all’interno del mondo virtuale del gioco. ↩︎

Post correlati

#TheRedComics

Giugno

A cura di Sophie Aiello, copy di Chiara Romano

La dura vita di una madre tech - Meme

TheRedCode Digest

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome
Logo de La Locanda del Tech

Vuoi diventare #tech content writer? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!