Menu
CoddyTech

Um pool com uma fila

Parte da seção Arquitetura de jogos no Unity do Journey de Unity da Coddy. Lição 38 de 50.

Um pool precisa de um lugar para guardar seus objetos reserva, e C# tem a coleção ideal para isso, Queue<T>: Enqueue adiciona um item ao final, Dequeue remove o item do início, e Count informa quantos estão esperando. Este aquário solta uma bolha a cada 0.3 segundos, e cada bolha volta ao 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 somente uma bolha nova precisa ter seu campo pool definido: uma reutilizada ainda o tem. A fila fornece primeiro a bolha que esperou por mais tempo: primeiro a entrar, primeiro 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 seu OnEnable imediatamente, e qualquer coisa ali deve ver a nova posição, não o lugar onde ela desapareceu da última vez. É também aí que um objeto reutilizado recomeça: Awake e Start foram executados uma vez, quando a bolha foi criada, e OnEnable é executado a cada Get.

challenge icon

Desafio

Médio

Pegadas na areia. As setas movem o Player (pronto). Trail.cs, no Player, deixa uma pegada a cada 1 unidade percorrida, chamando Get(position), e cada Footprint dura life (1.5) segundos. Hoje, Get instancia uma nova pegada a cada vez, e cada uma se destrói. Coloque-as em um pool:

  • Em Trail.cs, mantenha as pegadas extras em uma Queue<GameObject>. O campo trail de cada pegada criada por Trail precisa ser definido como este Trail.
  • Em Start, preencha o pool com prewarm (6) pegadas, criadas e desativadas, para que os primeiros passos não criem nada novo.
  • Get(position) pega uma pegada da fila quando houver uma; cria uma nova somente quando a fila estiver vazia; em seguida, posiciona a pegada e a ativa.
  • Return(footprint) desativa a pegada e a coloca na fila.
  • Em Footprint.cs, uma pegada conta sua idade e, após life segundos, volta usando trail.Return(gameObject), em vez de ser destruída. Uma pegada reutilizada dura novamente os 1.5 segundos completos.

Pressione Play, caminhe por um tempo e depois Check.

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 pré-inicializadas
    }

    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 ficam no pool
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

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