🎮 UnityDocs

LINQ en Unity: consultar colecciones

LINQ te deja filtrar, ordenar y transformar listas con una línea legible (Where, Select, OrderBy, FirstOrDefault). Muy cómodo, pero con una advertencia de rendimiento importante en el bucle de juego.

📄 ArtículoAvanzado✅ RevisadoUnity 6.0 LTSActualizado 2026-07-15
DificultadConceptual Código Matemáticas
Tiempo📖 Lectura 7 min · ⌨️ Práctica 20 min

Qué es LINQ#

LINQ te permite hacer consultas sobre colecciones (filtrar, ordenar, transformar) con código corto y legible, casi como una frase. Necesita using System.Linq;.

Compara. Sin LINQ, para quedarte con los enemigos vivos:

C#
List<Enemigo> vivos = new List<Enemigo>();
foreach (Enemigo e in enemigos)
    if (e.Vida > 0)
        vivos.Add(e);

Con LINQ, una línea:

C#
using System.Linq;

var vivos = enemigos.Where(e => e.Vida > 0).ToList();

Las operaciones más útiles#

C#
using System.Linq;

// Filtrar
var cercanos = enemigos.Where(e => e.Distancia < 10f);

// Transformar (proyectar)
var nombres = enemigos.Select(e => e.Nombre);

// Ordenar
var porVida = enemigos.OrderBy(e => e.Vida);
var porVidaDesc = enemigos.OrderByDescending(e => e.Vida);

// Encontrar uno
Enemigo jefe = enemigos.FirstOrDefault(e => e.EsJefe);   // null si no hay

// Comprobaciones
bool hayJefe = enemigos.Any(e => e.EsJefe);
int cuantos = enemigos.Count(e => e.Vida > 50);

// Agregados
int vidaTotal = enemigos.Sum(e => e.Vida);
Enemigo masFuerte = enemigos.OrderByDescending(e => e.Daño).First();
FirstOrDefault vs First

First lanza excepción si no encuentra nada; FirstOrDefault devuelve el valor por defecto (null para clases). Para buscar algo que puede no existir, usa FirstOrDefault y comprueba el resultado.

Encadenar operaciones#

Lo potente es combinarlas:

C#
// Los 3 enemigos vivos más cercanos, por nombre
var objetivos = enemigos
    .Where(e => e.Vida > 0)
    .OrderBy(e => e.Distancia)
    .Take(3)
    .Select(e => e.Nombre)
    .ToList();

Se lee casi como una frase: "de los enemigos, los vivos, ordenados por distancia, coge 3, sus nombres, a lista".

La advertencia de rendimiento (importante en Unity)#

No uses LINQ en Update ni en bucles calientes

LINQ es precioso, pero genera basura para el recolector (GC): crea iteradores y objetos intermedios en cada consulta. Ejecutarlo cada fotograma (en Update) o para miles de elementos provoca tirones. Reglas:

  • LINQ en código puntual (al inicio, en un evento, al abrir un menú): perfecto.
  • En el bucle de juego (Update, sobre muchos objetos): usa un foreach/for normal, que no asigna basura.
  • ¿Dudas? Mide con el Profiler la columna GC Alloc.

Deferred execution: una sutileza#

LINQ es perezoso: enemigos.Where(...) no filtra hasta que recorres el resultado (o llamas a .ToList(), .Count()...). Esto tiene una consecuencia:

C#
var consulta = enemigos.Where(e => e.Vida > 0);
// ...si aquí cambian las vidas...
foreach (var e in consulta) { }   // se evalúa AHORA, con los datos actuales

Si quieres "congelar" el resultado en el momento, añade .ToList().

Cuándo usar LINQ#

🧭 ¿Qué debería usar?
  • ¿Consulta puntual y quieres código legible (menú, inicio, evento)? → LINQ, adelante
  • ¿En Update o sobre miles de elementos por frame? → for/foreach normal (sin basura)
  • ¿Es una operación crítica de rendimiento? → mídela; a menudo el bucle manual gana

Errores frecuentes#

  • Usar LINQ en Update y provocar tirones por basura del GC.
  • First en vez de FirstOrDefault y petar cuando no hay resultados.
  • Olvidar using System.Linq;.
  • Esperar que la consulta se evalúe al declararla (es perezosa; usa .ToList() para materializarla).

Ponte a prueba#

📝 Pon a prueba lo aprendido

Resumen#

LINQ (using System.Linq;) consulta colecciones de forma legible: Where (filtrar), Select (transformar), OrderBy (ordenar), FirstOrDefault/Any/Count/Sum, y se encadenan. Es ideal para código puntual, pero evítalo en Update y bucles calientes porque genera basura para el GC (usa for/foreach). Recuerda que es de evaluación perezosa: .ToList() para materializar.

Fuentes y para profundizar