🎮 UnityDocs

Inyección de dependencias en Unity

Qué es la inyección de dependencias (DI), por qué reduce el acoplamiento frente a los Singletons y GetComponent, cómo hacerla a mano con interfaces, y cuándo un framework como VContainer o Zenject compensa. Con criterio para no complicar de más.

📄 ArtículoAvanzado✅ RevisadoUnity 6.0 LTSActualizado 2026-07-17
DificultadConceptual Código Matemáticas
Tiempo📖 Lectura 9 min

El problema: dependencias escondidas#

Cuando una clase crea o busca por su cuenta lo que necesita, queda atada a ello:

C#
// ❌ Enemigo atado a implementaciones concretas
class Enemigo : MonoBehaviour
{
    void Morir()
    {
        AudioManager.Instance.Reproducir(sonido);   // Singleton concreto
        FindObjectOfType<PuntuacionUI>().Sumar(10);  // búsqueda frágil y lenta
    }
}

Esto es difícil de probar (no puedes cambiar el AudioManager por uno falso), frágil (si desaparece el Singleton, peta) y opaco (no ves de qué depende sin leer el cuerpo).

La idea: que te den las dependencias#

Inyección de dependencias (DI): en vez de crear/buscar lo que necesitas, lo recibes desde fuera. La clase declara qué necesita (idealmente como interfaz) y otro se lo entrega.

C#
interface IAudio { void Reproducir(AudioClip clip); }

class Enemigo : MonoBehaviour
{
    private IAudio audio;
    private IPuntuacion puntuacion;

    // Recibe sus dependencias (aquí, un inicializador)
    public void Init(IAudio audio, IPuntuacion puntuacion)
    {
        this.audio = audio;
        this.puntuacion = puntuacion;
    }

    void Morir()
    {
        audio.Reproducir(sonido);   // no sabe ni le importa quién lo implementa
        puntuacion.Sumar(10);
    }
}

Ahora Enemigo depende de abstracciones (la letra D de SOLID): en el juego le pasas el audio real; en un test, uno falso.

DI a mano (sin framework)#

En muchos juegos no necesitas nada más que esto: un objeto "compositor" (a veces el propio GameManager de arranque) que crea las implementaciones y las reparte. Es la forma más simple y transparente, y para proyectos pequeños/medianos suele bastar.

ScriptableObject como dependencia inyectable

Un ScriptableObject es una dependencia inyectable buenísima en Unity: arrastras el mismo asset (un canal de eventos, una config) a varios componentes desde el Inspector. Es "inyección" a mano, visual y sin código de fontanería.

Frameworks de DI: VContainer / Zenject#

Cuando el proyecto crece y repartir dependencias a mano se vuelve tedioso, un contenedor de DI lo automatiza: registras "cuando alguien pida IAudio, dale AudioReal" y el contenedor inyecta todo solo (en constructores, campos o métodos).

  • VContainer: moderno, muy rápido y ligero; la recomendación actual para Unity.
  • Zenject/Extenject: veterano, muy completo, más pesado.
No metas un framework de DI en un juego pequeño

Un contenedor de DI añade una curva de aprendizaje y "magia" que oscurece el flujo. Para un Pong o un prototipo es sobreingeniería: la DI a mano con interfaces es suficiente y más clara. Introduce el framework cuando el reparto manual sea un dolor real, no antes.

DI vs Singleton#

⚖️ Comparativa · Inyección vs Singleton
Inyección de dependenciasSingleton
AcoplamientoBajo (dependes de interfaces)Alto (dependes de la clase concreta global)
TestabilidadAlta (inyectas dobles)Baja (estado global difícil de aislar)
Visibilidad de dependenciasExplícita (las declaras)Oculta (aparecen dentro de métodos)
Coste inicialAlgo más de fontaneríaCero, muy rápido de escribir
RiesgoSobreingeniería si abusasEstado global y acoplamiento si abusas

Errores frecuentes#

  • Llamar "DI" a seguir usando Singletons por dentro.
  • Inyectar clases concretas en vez de interfaces (pierdes casi toda la ventaja).
  • Adoptar Zenject/VContainer en un prototipo (complejidad que no necesitas).
  • Inyectar absolutamente todo, hasta lo trivial: acaba en fontanería infinita.

Ponte a prueba#

📝 Pon a prueba lo aprendido

Resumen#

La inyección de dependencias hace que una clase reciba lo que necesita (como interfaz) en vez de crearlo o buscarlo, reduciendo el acoplamiento y haciéndola testable: es la letra D de SOLID en acción, y la alternativa sana al abuso de Singletons. En la mayoría de juegos, hacerla a mano (un compositor que reparte, o ScriptableObjects por el Inspector) es suficiente; los frameworks como VContainer aportan cuando el proyecto crece. Como siempre: sin sobreingeniar.

Fuentes y para profundizar