El problema: assets y memoria#
Si todo lo referencias directamente (arrastrando prefabs), Unity lo mete en la build y, a menudo, lo carga aunque no lo uses todavía. En juegos grandes eso hincha la memoria y el tamaño del ejecutable. El viejo truco Resources.Load empeora las cosas: todo lo que hay en carpetas Resources/ se empaqueta y alarga el arranque.
Addressables resuelve esto: cada asset tiene una dirección (un nombre) y lo cargas y liberas cuando quieres, esté en la build o en un servidor.
Package Manager → Addressables. Marca un asset como Addressable en su Inspector (una casilla) y aparece en la ventana Window → Asset Management → Addressables → Groups, donde se organizan en grupos y se les ponen etiquetas.
Cargar y —clave— liberar#
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class SpawnAddressable : MonoBehaviour
{
[SerializeField] private AssetReferenceGameObject enemigoRef; // referencia por dirección
private AsyncOperationHandle<GameObject> handle;
public async void Aparecer()
{
handle = enemigoRef.InstantiateAsync(transform.position, Quaternion.identity);
await handle.Task; // carga bajo demanda (puede venir de disco o red)
}
void OnDestroy()
{
// Liberar: sin esto, el asset se queda en memoria
if (handle.IsValid()) Addressables.ReleaseInstance(handle);
}
}Addressables usa conteo de referencias: cada LoadAssetAsync/InstantiateAsync suma, y necesita su Release/ReleaseInstance para restar. Si cargas y no liberas, el asset nunca sale de memoria (una fuga). Guarda el handle y libéralo en OnDestroy o al cambiar de escena. Ver gestión de memoria.
AssetReference en vez de string#
Puedes cargar por texto (Addressables.LoadAssetAsync<GameObject>("enemigo")), pero es frágil. Mejor una AssetReference ([SerializeField] private AssetReference ...): la arrastras en el Inspector, no hay erratas y sobrevive a renombrados.
Para qué brilla#
- Menos memoria: cargas el nivel/jefe actual, liberas el anterior.
- Build más pequeña: contenido que se descarga aparte (Remote groups) en vez de meterlo todo.
- DLC y actualizaciones de contenido: publicas assets nuevos en un servidor sin reenviar el ejecutable.
- Labels: cargas por etiqueta ("todos los enemigos del bioma nieve") de golpe.
Addressables vs Resources#
| Addressables | Resources (legado) | |
|---|---|---|
| Carga bajo demanda | Sí, async | Sí, pero síncrona y torpe |
| Liberar memoria | Explícito y controlado | Difícil / global |
| Contenido remoto (DLC) | Sí | No |
| Efecto en el arranque/build | Controlado por grupos | Empaqueta TODO (alarga arranque) |
| Recomendado en proyectos nuevos | Sí | No (evítalo) |
Errores frecuentes#
- Cargar y no liberar (fuga de memoria que crece con el tiempo).
- Seguir usando carpetas Resources/ para todo (alarga el arranque, hincha la build).
- Cargar por string con erratas en vez de
AssetReference. - Cargar de forma síncrona algo que viene de red (usa el flujo async).
- No probar el catálogo tras cambiar grupos (hay que Build el contenido Addressables).
Ponte a prueba#
Resumen#
Addressables da a cada asset una dirección para cargarlo y liberarlo bajo demanda, esté en la build o en un servidor: menos memoria, build más pequeña y contenido descargable (DLC). Usa AssetReference en vez de strings, y respeta el conteo de referencias: cada carga necesita su Release o tendrás fugas. Sustituye al frágil Resources, que deberías evitar en proyectos nuevos. Es una pieza central de la optimización y la gestión de memoria en producción.