Menu
CoddyTech

Un pool con una coda

Fa parte della sezione Architettura dei giochi in Unity del percorso Unity di Coddy. Lezione 47 di 64.

A una piscina serve un posto dove conservare gli oggetti di riserva, e C# ha la raccolta adatta: Queue<T>: Enqueue aggiunge un elemento in fondo, Dequeue prende quello in testa e Count indica quanti sono in attesa. Questo acquario fa salire una bolla ogni 0.3 secondi, e ogni bolla torna nella piscina quando raggiunge la superficie:

using System.Collections.Generic;
using UnityEngine;

public class BubblePool : MonoBehaviour
{
    public GameObject bubblePrefab;
    private Queue<GameObject> pool = new Queue<GameObject>();
    private float timer;

    void Update()
    {
        timer += Time.deltaTime;
        if (timer >= 0.3f)
        {
            timer = 0f;
            Get(new Vector3(Random.Range(-2f, 2f), 0f, 0f));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject bubble;
        if (pool.Count > 0)
        {
            bubble = pool.Dequeue();
        }
        else
        {
            bubble = Instantiate(bubblePrefab);
            bubble.GetComponent<Bubble>().pool = this;
        }
        bubble.transform.position = position;
        bubble.SetActive(true);
        return bubble;
    }

    public void Return(GameObject bubble)
    {
        bubble.SetActive(false);
        pool.Enqueue(bubble);
    }
}
// Bubble.cs, sul prefab della bolla
public BubblePool pool;

void Update()
{
    transform.Translate(0f, 2f * Time.deltaTime, 0f);
    if (transform.position.y > 5f) pool.Return(gameObject);
}

Get controlla prima Count, perché Dequeue su una coda vuota genera un'eccezione InvalidOperationException. Solo allora esegue Instantiate, e solo a una bolla nuova serve impostare il campo pool: una riutilizzata lo conserva. La coda restituisce per prima la bolla che ha atteso più a lungo, secondo il principio «primo entrato, primo uscito». Una bolla in superficie chiama Return invece di Destroy e rimane nella scena, inattiva, fino al successivo Get.

Get posiziona la bolla prima di SetActive(true), perché attivarla esegue subito il suo OnEnable, e tutto ciò che si trova lì dovrebbe vedere la nuova posizione, non quella in cui era scomparsa l'ultima volta. È anche lì che un oggetto riutilizzato ricomincia: Awake e Start sono stati eseguiti una volta, quando la bolla è stata creata, mentre OnEnable viene eseguito a ogni Get.

challenge icon

Sfida

Medio

Metti in pool le impronte invece di distruggerle.

  1. In Trail, tieni le impronte di scorta in una Queue<GameObject>. Return(footprint) la disattiva e la inserisce nella coda; Start crea prewarm impronte e le restituisce.
  2. Get(position) estrae un’impronta di scorta dalla coda (oppure ne crea una), la posiziona e la attiva.
  3. In Footprint, sostituisci Destroy: azzera l’età in OnEnable; dopo life secondi, trail.Return(gameObject).

Premi «Gioca» e cammina: le impronte svaniscono dopo 1.5 secondi. Poi premi «Verifica».

Provalo tu

using System.Collections.Generic;
using UnityEngine;

public class Trail : MonoBehaviour
{
    public GameObject footprintPrefab;
    public float step = 1f;
    public int prewarm = 6;
    private Vector3 lastDrop;

    void Start()
    {
        lastDrop = transform.position;
        // Riempi il pool con impronte preparate in anticipo
    }

    void Update()
    {
        if (Vector3.Distance(transform.position, lastDrop) >= step)
        {
            lastDrop = transform.position;
            Get(new Vector3(transform.position.x, 0.02f, transform.position.z));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject footprint = Instantiate(footprintPrefab, position, Quaternion.identity);
        footprint.GetComponent<Footprint>().trail = this;
        return footprint;
    }

    public void Return(GameObject footprint)
    {
        // Le impronte di riserva attendono nel pool
    }
}

Tutte le lezioni di Architettura dei giochi in Unity

Esercitati da solo: Playground Unity