Menu
CoddyTech

Um pool com uma fila

Parte da seção Arquitetura de Jogos no Unity do Journey de Unity da Coddy. Lição 47 de 64.

Um pool precisa de um lugar para guardar seus objetos extras, e C# tem a coleção ideal para isso, Queue<T>: Enqueue adiciona um item no final, Dequeue pega o que está no início, e Count informa quantos estão esperando. Este aquário solta uma bolha a cada 0.3 segundos, e cada bolha volta para o pool na superfície:

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, no prefab da bolha
public BubblePool pool;

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

Get verifica primeiro Count, porque Dequeue em uma fila vazia lança uma InvalidOperationException. Só então chama Instantiate, e apenas uma bolha nova precisa ter seu campo pool definido: uma reutilizada ainda o mantém. A fila entrega primeiro a bolha que está esperando há mais tempo: a primeira a entrar é a primeira a sair. Uma bolha na superfície chama Return em vez de Destroy, e permanece na cena, inativa, até o próximo Get.

Get posiciona a bolha antes de SetActive(true), porque ativá-la executa OnEnable imediatamente, e qualquer coisa nesse método deve encontrar a nova posição, não aquela em que ela desapareceu da última vez. É também aí que um objeto reutilizado começa de novo: Awake e Start são executados uma vez, quando a bolha é criada, e OnEnable é executado a cada Get.

challenge icon

Desafio

Médio

Armazene as pegadas em um pool em vez de destruí-las.

  1. Em Trail, mantenha as reservas em uma Queue<GameObject>. Return(footprint) desativa o objeto e o adiciona à fila; Start cria prewarm pegadas e as devolve.
  2. Get(position) retira uma reserva da fila (ou cria uma), posiciona-a e a ativa.
  3. Em Footprint, substitua Destroy: redefina a idade em OnEnable; após life segundos, chame trail.Return(gameObject).

Pressione “Jogar” e caminhe: as pegadas desaparecem após 1.5 segundos. Depois, pressione “Verificar”.

Experimente você mesmo

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;
        // Preencha o pool com pegadas preparadas antecipadamente
    }

    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)
    {
        // As pegadas sobressalentes aguardam no pool
    }
}

Todas as lições de Arquitetura de Jogos no Unity

Pratique por conta própria: Playground de Unity