Menu
CoddyTech

Un pool con una cola

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 38 de 50.

Un pool necesita un lugar donde guardar sus objetos de repuesto, y C# tiene la colección adecuada: Queue<T>: Enqueue añade un elemento al final, Dequeue toma el que está al principio y Count indica cuántos esperan. Este acuario hace subir una burbuja cada 0.3 segundos, y cada burbuja vuelve al pool al llegar a 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, en el prefab de la burbuja
public BubblePool pool;

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

Get comprueba primero Count, porque Dequeue en una cola vacía lanza una InvalidOperationException. Solo entonces ejecuta Instantiate, y solo hay que asignar el campo pool a una burbuja nueva: una reutilizada ya lo tiene. La cola entrega primero la burbuja que ha esperado más tiempo; es decir, la primera en entrar es la primera en salir. Una burbuja que llega a la superficie llama a Return en lugar de Destroy, y permanece en la escena, inactiva, hasta la próxima llamada a Get.

Get coloca la burbuja antes de SetActive(true), porque activarla ejecuta OnEnable inmediatamente, y cualquier código que haya allí debe ver la nueva posición, no el lugar donde desapareció la última vez. Ahí también es donde un objeto reutilizado empieza de nuevo: Awake y Start se ejecutaron una vez, cuando se creó la burbuja, y OnEnable se ejecuta con cada llamada a Get.

challenge icon

Desafío

Intermedio

Huellas en la arena. Las flechas hacen caminar al Player (listo). Trail.cs, en el Player, deja una huella cada 1 unidad recorrida llamando a Get(position), y cada Footprint dura life (1.5) segundos. Hoy, Get crea una huella nueva cada vez y cada una se destruye sola. Crea un grupo de objetos para reutilizarlos:

  • En Trail.cs, guarda las huellas sobrantes en una Queue<GameObject>. El campo trail de cada huella que cree Trail debe estar establecido en esta instancia de Trail.
  • En Start, llena el grupo con prewarm (6) huellas, creadas y desactivadas, para que los primeros pasos no creen nada nuevo.
  • Get(position) toma una huella de la cola si hay alguna, y crea una nueva solo cuando está vacía; después coloca la huella y la activa.
  • Return(footprint) desactiva la huella y la coloca en la cola.
  • En Footprint.cs, una huella cuenta su antigüedad y, después de life segundos, vuelve mediante trail.Return(gameObject) en lugar de destruirse. Una huella reutilizada vuelve a durar sus 1.5 segundos completos.

Pulsa Play, camina un rato y después pulsa Check.

Pruébalo tú mismo

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;
        // Llena la reserva con huellas precalentadas
    }

    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)
    {
        // Las huellas de repuesto esperan en la reserva
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Arquitectura de juegos en Unity