Optimización con Object Pooling en Unity

Reduce picos de CPU y basura de memoria reutilizando objetos en lugar de instanciarlos y destruirlos constantemente.

Instanciar y destruir objetos en bucle (balas, partículas, enemigos) provoca coste extra de CPU y presión sobre el recolector de basura.

Object Pooling reutiliza instancias existentes para evitar crear y destruir continuamente durante el gameplay.

Unity incluye utilidades en `UnityEngine.Pool` para implementar pools con callbacks de creación, activación y liberación.

Esta práctica está alineada con `contenido.md`: optimizar rendimiento evitando picos de procesamiento en sistemas repetitivos.

  • El coste no suele verse con pocos objetos, pero escala mal en escenas activas.
  • Cada creación implica reservar memoria y configurar componentes; cada destrucción deja trabajo al recolector de basura.
  • En sistemas de disparo rápido, este patrón genera microcortes perceptibles y variaciones en frame time.
  • La optimización efectiva consiste en evitar churn de objetos temporales de alta frecuencia.
  • Menos alloc/dealloc por frame.

Por qué `Instantiate`/`Destroy` puede degradar rendimiento

El coste no suele verse con pocos objetos, pero escala mal en escenas activas.

Cada creación implica reservar memoria y configurar componentes; cada destrucción deja trabajo al recolector de basura.

En sistemas de disparo rápido, este patrón genera microcortes perceptibles y variaciones en frame time.

La optimización efectiva consiste en evitar churn de objetos temporales de alta frecuencia.

  • Menos alloc/dealloc por frame.
  • Menos presión de GC.
  • Mayor estabilidad de FPS.

Pool básico con `ObjectPool<T>`

Define cómo crear, activar, desactivar y destruir objetos del pool.

`Get()` toma un objeto disponible (o crea uno si hace falta) y `Release()` lo devuelve para reutilización.

En `OnGet` activa el objeto y resetea estado mínimo; en `OnRelease` desactiva y limpia datos temporales.

Establece límites (`maxSize`) para controlar memoria y evitar crecimiento ilimitado.

Buenas prácticas de producción

Pool sin disciplina puede ocultar errores de estado entre reutilizaciones.

Resetea estado interno al liberar: velocidad, vida temporal, timers y referencias de objetivo.

No mezcles objetos de distintos tipos en el mismo pool si tienen ciclo de vida diferente.

Mide antes y después con Profiler para validar impacto real del cambio.

Unity
17

Optimización con Object Pooling en Unity

Reduce picos de CPU y basura de memoria reutilizando objetos en lugar de instanciarlos y destruirlos constantemente.

Código del tema: GameObject + Component = comportamiento

📘 Teoría

Por qué `Instantiate`/`Destroy` puede degradar rendimiento

El coste no suele verse con pocos objetos, pero escala mal en escenas activas.

Cada creación implica reservar memoria y configurar componentes; cada destrucción deja trabajo al recolector de basura.

En sistemas de disparo rápido, este patrón genera microcortes perceptibles y variaciones en frame time.

La optimización efectiva consiste en evitar churn de objetos temporales de alta frecuencia.

  • Menos alloc/dealloc por frame.
  • Menos presión de GC.
  • Mayor estabilidad de FPS.

Pool básico con `ObjectPool<T>`

Define cómo crear, activar, desactivar y destruir objetos del pool.

1

`Get()` toma un objeto disponible (o crea uno si hace falta) y `Release()` lo devuelve para reutilización.

2

En `OnGet` activa el objeto y resetea estado mínimo; en `OnRelease` desactiva y limpia datos temporales.

3

Establece límites (`maxSize`) para controlar memoria y evitar crecimiento ilimitado.

Implementación simple de pool para proyectiles
using UnityEngine;
using UnityEngine.Pool;

public class BulletPool : MonoBehaviour
{
    public GameObject bulletPrefab;
    private ObjectPool<GameObject> pool;

    void Awake()
    {
        pool = new ObjectPool<GameObject>(
            CreateBullet,
            OnGetBullet,
            OnReleaseBullet,
            OnDestroyBullet,
            collectionCheck: false,
            defaultCapacity: 20,
            maxSize: 100
        );
    }

    GameObject CreateBullet() => Instantiate(bulletPrefab);

    void OnGetBullet(GameObject bullet) => bullet.SetActive(true);

    void OnReleaseBullet(GameObject bullet) => bullet.SetActive(false);

    void OnDestroyBullet(GameObject bullet) => Destroy(bullet);

    public GameObject Spawn() => pool.Get();

    public void Despawn(GameObject bullet) => pool.Release(bullet);
}

Buenas prácticas de producción

Pool sin disciplina puede ocultar errores de estado entre reutilizaciones.

1

Resetea estado interno al liberar: velocidad, vida temporal, timers y referencias de objetivo.

2

No mezcles objetos de distintos tipos en el mismo pool si tienen ciclo de vida diferente.

3

Mide antes y después con Profiler para validar impacto real del cambio.

🧪 Aprende probando

Ejemplo Ejemplo guiado Construye un pool de balas y reemplaza un flujo de `Instantiate` directo por `Get()`.

🏁 Retos

Reto Reto práctico Implementa un pool con `ObjectPool<GameObject>` y usa `Get()`/`Release()` en lugar de instanciar y destruir siempre.

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros 😉.

Esta la hice en febrero de 2026 para facilitar el aprendizaje de mis alumnxs. Aprender desarrollo web practicando. La idea es que crezca semanalmente con nuevos temas, tests y retos.

Inspirado en MDN, en W3Schools, en Codepen, en el crack de Manz y en mil sitios de documentación sobre desarrollo web. Quería aportar además de bloques teóricos con ejemplos, la gamificación de los retos y el sistema de test que ya tenía en culTest .

Si te gustó, si no te gustó, si quieres saludarme, o invitarme a 🍻 no dudes en escribirme en cristianeslava@gmail.com .