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.
Desafío
IntermedioHuellas 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 unaQueue<GameObject>. El campotrailde 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 delifesegundos, vuelve mediantetrail.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
}
}
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
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modular4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botín7Máquinas de estados
Estados como clasesUna máquina de estadosTransicionesCerebros de enemigosRepaso: estados de puertas10Proyecto: Superviviente de la arena
El héroeTipos de enemigos2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: tecla de interacción5ScriptableObjects
Recursos de datosEstadísticas de armasConfiguración compartidaOleadas como datosRepaso: base de datos de objetos3Eventos
Eventos de C# en UnitySuscribirse en OnEnableCampos de UnityEventLos eventos controlan la interfazRepaso: ventana emergente de logro6Guardar con JSON
JsonUtilityGuardar la partidaCargar y valores predeterminadosRepaso: ranuras de guardado9Pool de objetos
Por qué usar un pool de objetosUn pool con una colaObjectPool de UnityResumen: pool de balas