miércoles, 22 de octubre de 2025

2025: El renacimiento del "solo dev" gracias a la IA

 


Desde hace eones, la industria del videojuego ha estado dominada por grandes estudios, equipos masivos y presupuestos de millones. Para muestra, la estadística de ventas de juegos de STEAM que superan los 100.000 € al año es la misma (juego arriba, juego abajo) desde hace 12 años. Pero si analizamos las cosas desde 2025, algo está cambiando profundamente: estamos asistiendo al renacimiento del desarrollador en solitario, impulsado por un aliado inesperado y poderoso — la inteligencia artificial.

De la locura utópica a la realidad.

Lo que hace unos años parecía una fantasía —una sola persona creando mundos completos, con arte, música, narrativa y código de nivel profesional— hoy se está convirtiendo en una realidad tangible.
Herramientas de IA generativa permiten que los solo devs hagan en semanas lo que antes requería un equipo entero durante meses. Y lo más importante: les permiten centrarse en la creatividad, en la visión, en la emoción del juego… y no solo en la ejecución técnica.

El nuevo superhéroe, el solo dev.

En 2025, un desarrollador independiente ya no está solo. A su lado tiene un ecosistema de inteligencias artificiales especializadas que le ayudan en cada fase del desarrollo:

  • 🎨 Arte y estilo visual: modelos como Leonardo.ai o Krikey AI generan concept art, personajes y escenarios con coherencia estética y múltiples variaciones. Otras como Meshy te hacen más fácil el 3D.

  • 🎼 Música dinámica y adaptativa: herramientas como Aiva o Suno permiten crear bandas sonoras que responden al tono del juego o a las acciones del jugador.

  • 🗣️ Narrativa viva: ChatGPT y otros modelos de lenguaje ayudan a generar diálogos naturales, misiones secundarias o sistemas narrativos interactivos.

  • 👾 Código asistido: GitHub Copilot y modelos de IA especializados en game engines escriben o corrigen scripts en C#, Unreal Blueprints o Python, acelerando la iteración y reduciendo errores.

  • 🧩 Prototipado y testing: la IA automatiza la detección de bugs, ajusta el balance del juego e incluso sugiere mejoras en la jugabilidad analizando el comportamiento de los testers humanos o simulados.

Una nueva generación de creadores para una nueva generación de consumidores.

Gracias a estas herramientas, está emergiendo una nueva generación de desarrolladores independientes: creadores híbridos, capaces de diseñar, escribir, programar y dirigir su propio universo digital.
Muchos de los éxitos virales de 2025 nacen en estudios unipersonales, donde la IA no sustituye la visión del creador, sino que multiplica su alcance.

El resultado es una explosión de originalidad: juegos más personales, arriesgados y emocionales, que escapan de las fórmulas repetidas de las grandes editoras. Las cifras están ahí, los grandes títulos en caída libre y juegos indie "solo dev" que ya tienen miles y en algún caso, millones de copias vendidas.

Y ya que hablamos de editoras, o se ponen las pilas o desaparecen a la vuelta de 5 años. El mercado, ya no solo del videojuego, sino del audiovisual en general, está cambiando rápidamente a un nuevo mundo.

La IA no sustituye, amplifica.

El miedo a que la IA reemplace al talento humano está dando paso a una comprensión más profunda: la inteligencia artificial no crea por sí sola. Necesita dirección, intención y sensibilidad.
El solo dev del futuro no es un programador aislado, sino un director creativo asistido por IA, capaz de traducir ideas en experiencias jugables con una velocidad y calidad nunca vistas.

El futuro es de las personas.

La democratización del desarrollo gracias a la IA está cambiando las reglas. Si en los 90 bastaba una buena idea para destacar, en 2025 basta una buena idea bien guiada por IA para llegar a millones de jugadores.
El futuro de los videojuegos no será de los gigantes, sino de quienes se atrevan a soñar, experimentar y crear en solitario… con una legión de inteligencias artificiales como compañeras de viaje.

viernes, 1 de agosto de 2025

Patrón Observer en Unity: eventos limpios sin acoplar objetos



Último post de la serie de patrones que hay que saberse para hacer videojuegos.

Cuándo usarlo: HUD, logros, misiones, sonido, spawns… cualquier reacción a “algo pasó”. Como principal ventaja es que sustituyes referencias directas por suscripciones, lo que facilita pruebas y reutilización (el emisor no sabe quién escucha).

Opción A — C# events (rápido y fuerte)

Event Hub

using System; public static class GameEvents { public static event Action<int> OnCoinCollected; public static event Action OnPlayerDied; public static void CoinCollected(int amount) => OnCoinCollected?.Invoke(amount); public static void PlayerDied() => OnPlayerDied?.Invoke(); }

Emisor

using UnityEngine; public class Coin : MonoBehaviour { public int amount = 1; void OnTriggerEnter(Collider other) { if (!other.CompareTag("Player")) return; GameEvents.CoinCollected(amount); Destroy(gameObject); } }

Observadores

using UnityEngine; using UnityEngine.UI; public class HudCoins : MonoBehaviour { public Text label; int total; void OnEnable() => GameEvents.OnCoinCollected += Handle; void OnDisable() => GameEvents.OnCoinCollected -= Handle; void Handle(int a){ total += a; label.text = total.ToString(); } } public class GameOverScreen : MonoBehaviour { public GameObject panel; void OnEnable() => GameEvents.OnPlayerDied += Show; void OnDisable() => GameEvents.OnPlayerDied -= Show; void Show(){ panel.SetActive(true); } }

Opción B — Event Channels con ScriptableObject (editor-friendly)

Canal

using UnityEngine; using UnityEngine.Events; [CreateAssetMenu(menuName="Events/Int Event Channel")] public class IntEventChannel : ScriptableObject { public UnityAction<int> OnRaised; public void Raise(int value) => OnRaised?.Invoke(value); }

Emisor/Listener

// Emisor (asignas el canal desde el inspector) public class CoinEmitter : MonoBehaviour { public IntEventChannel CoinChannel; public int amount = 1; void OnTriggerEnter(Collider c) { if (c.CompareTag("Player")) CoinChannel.Raise(amount); } } // Listener using UnityEngine; using UnityEngine.UI; public class CoinListener : MonoBehaviour { public IntEventChannel CoinChannel; public Text label; int total; void OnEnable() => CoinChannel.OnRaised += Add; void OnDisable() => CoinChannel.OnRaised -= Add; void Add(int a){ total += a; label.text = total.ToString(); } }

lunes, 16 de junio de 2025

Patrón State en Unity: IA y jugador (sin if gigantes)



Este post va dedicado a todos los que alguna vez nos tuvimos que pelear con una MEF. 

Problema clásico: un personaje tiene estados (Idle, Run, Jump, Attack…). Con tantos if/else el código explota y el rendimiento más.
Solución: encapsula cada estado en su clase y cambia de uno a otro con una máquina de estados.

Consejillos para no perderse: puedes añadir estados sin tocar los existentes y te aconsejo que hagas un esquema en un papel de estados a la "vieja usanza" antes de codificar.

Interfaz de estado

public interface IState { void Enter(); void Tick(); void Exit(); }

StateMachine reutilizable

using UnityEngine; public class StateMachine : MonoBehaviour { IState _current; public void Set(IState next) { _current?.Exit(); _current = next; _current?.Enter(); } void Update() => _current?.Tick(); }

Estados concretos (ejemplo jugador)

using UnityEngine; public class PlayerContext : MonoBehaviour { public Rigidbody rb; public float moveSpeed = 5f; public bool IsGrounded; public Vector2 MoveInput; public bool JumpPressed; } public class IdleState : IState { readonly PlayerContext ctx; readonly StateMachine sm; public IdleState(PlayerContext c, StateMachine m){ ctx=c; sm=m; } public void Enter() { /* anim Idle */ } public void Tick() { if (ctx.MoveInput.sqrMagnitude > 0.01f) sm.Set(new RunState(ctx, sm)); if (ctx.JumpPressed && ctx.IsGrounded) sm.Set(new JumpState(ctx, sm)); } public void Exit() {} } public class RunState : IState { readonly PlayerContext ctx; readonly StateMachine sm; public RunState(PlayerContext c, StateMachine m){ ctx=c; sm=m; } public void Enter(){ /* anim Run */ } public void Tick() { var dir = new Vector3(ctx.MoveInput.x, 0, ctx.MoveInput.y); ctx.rb.velocity = new Vector3(dir.x * ctx.moveSpeed, ctx.rb.velocity.y, dir.z * ctx.moveSpeed); if (dir.sqrMagnitude < 0.01f) sm.Set(new IdleState(ctx, sm)); if (ctx.JumpPressed && ctx.IsGrounded) sm.Set(new JumpState(ctx, sm)); } public void Exit(){} } public class JumpState : IState { readonly PlayerContext ctx; readonly StateMachine sm; bool jumped; public JumpState(PlayerContext c, StateMachine m){ ctx=c; sm=m; } public void Enter(){ jumped=false; } public void Tick() { if (!jumped){ ctx.rb.AddForce(Vector3.up * 5f, ForceMode.VelocityChange); jumped = true; } if (ctx.IsGrounded && ctx.rb.velocity.y <= 0.01f) sm.Set(new IdleState(ctx, sm)); } public void Exit(){} }

Bootstrap

using UnityEngine; [RequireComponent(typeof(StateMachine), typeof(PlayerContext))] public class PlayerBootstrap : MonoBehaviour { void Start() { var sm = GetComponent<StateMachine>(); var ctx = GetComponent<PlayerContext>(); sm.Set(new IdleState(ctx, sm)); } }


jueves, 3 de abril de 2025

ECS en Unity: componiendo juegos que escalan



Por qué te importa: el modelo Entidad-Componente-Sistema separa datos, comportamiento y procesamiento, reduciendo dependencias y haciendo fácil añadir/quitar habilidades.

Qué significa ECS en Unity

  • Entidad: un ID o GameObject que “agrega cosas”.

  • Componente (datos): trocitos de estado (salud, velocidad…).

  • Sistema (lógica): procesa lotes de entidades con ciertos componentes.

Nota: Puedes aplicar la filosofía ECS con MonoBehaviour (composición clásica) o con Unity Entities (DOTS).

Te irá bien cuando tengas muchos objetos similares (bullets, partículas con lógica, enjambres) y cuando necesites rendimiento y sistemas desacoplados.

Aquí va un enfoque práctico con MonoBehaviour + un ejemplo mínimo en DOTS.

Enfoque práctico con MonoBehaviour

Componentes de datos (POCOs)

// Datos puros (no heredan de MonoBehaviour) [System.Serializable] public class HealthData { public int Max = 100; public int Current = 100; } [System.Serializable] public class MoveData { public float Speed = 5f; }

Bridges en GameObjects

using UnityEngine; public class Health : MonoBehaviour { public HealthData Data = new HealthData(); public bool IsDead => Data.Current <= 0; } public class Mover : MonoBehaviour { public MoveData Data = new MoveData(); public Vector3 Direction; }

Sistema (procesa muchos)

using UnityEngine; public class MovementSystem : MonoBehaviour { Mover[] movers; void Awake() => movers = FindObjectsOfType<Mover>(); void Update() { float dt = Time.deltaTime; foreach (var m in movers) { if (!m.enabled) continue; m.transform.position += m.Data.Speed * dt * m.Direction.normalized; } } }

Añadir/quitar comportamiento

// Convertir un NPC en volador: añade un componente "Fly" public class Fly : MonoBehaviour { public float HoverAmplitude = 0.25f; public float HoverSpeed = 3f; float t; void Update() { t += Time.deltaTime * HoverSpeed; transform.position += Vector3.up * Mathf.Sin(t) * HoverAmplitude * Time.deltaTime; } 


Variante mínima con Unity Entities (DOTS)

(requieres el package Entities; nombres pueden variar según versión)

// Components (IComponentData) using Unity.Entities; using Unity.Mathematics; public struct MoveSpeed : IComponentData { public float Value; } public struct Direction : IComponentData { public float3 Value; }

// System (ISystem / SystemBase) using Unity.Burst; using Unity.Entities; using Unity.Transforms; using Unity.Mathematics; [BurstCompile] public partial struct MovementSystem : ISystem { public void OnUpdate(ref SystemState state) { float dt = SystemAPI.Time.DeltaTime; foreach (var (speed, dir, transform) in SystemAPI.Query<RefRO<MoveSpeed>, RefRO<Direction>, RefRW<LocalTransform>>()) { var t = transform.ValueRO; t.Position += dir.ValueRO.Value * speed.ValueRO.Value * dt; transform.ValueRW = t; } } }

miércoles, 12 de febrero de 2025

3 patrones de diseño que todo desarrollador de videojuegos debe conocer



Detrás de cada videojuego hay mucho más que arte, música y gameplay: hay una arquitectura de software inteligente.

Los patrones de diseño son estructuras recurrentes que ayudan a resolver problemas comunes en la programación de juegos, permitiendo que el código sea más limpio, flexible y fácil de mantener.

En este artículo intentaré explicar tres patrones esenciales que todo desarrollador de videojuegos debería dominar o, al menos, conocer.


1. Patrón Entidad-Componente-Sistema (ECS).

El ECS es uno de los modelos más usados en motores modernos como Unity, Godot 4 o Unreal Engine.


Rompe con la herencia tradicional (donde cada objeto del juego es una clase con miles de atributos) y apuesta por una arquitectura basada en composición:

  • Entidad: representa un objeto del juego (una ID, sin lógica).

  • Componente: define datos (posición, salud, velocidad, inventario...).

  • Sistema: contiene la lógica que actúa sobre conjuntos de componentes (física, IA, render, input...).

Ventaja: es increíblemente flexible. Permite añadir, quitar o modificar comportamientos sin romper el código existente.
Ejemplo: puedes convertir un NPC en un enemigo volador simplemente añadiendo el componente “FlyBehavior” sin tocar su clase base.


2. Patrón Estado (State Pattern).

En los videojuegos, los objetos y personajes cambian de comportamiento según su estado actual: caminar, atacar, morir, hablar, etc.
El patrón Estado encapsula esos comportamientos en clases independientes y permite cambiar entre ellos dinámicamente.

  • Contexto: el objeto que cambia de estado (por ejemplo, el jugador).

  • Estados: clases que definen el comportamiento (IdleState, RunState, JumpState...).

  • Transiciones: controlan cuándo y cómo se cambia de un estado a otro.

Ventaja: evita los temidos “switch gigantes” llenos de if/else y facilita añadir nuevos comportamientos.
Ejemplo: un enemigo pasa de “PatrollingState” a “ChasingState” cuando detecta al jugador, sin romper el resto de la lógica.


3. Patrón Observador (Observer Pattern).

Perfecto para manejar eventos dentro del juego sin crear dependencias entre objetos.
Permite que ciertos objetos (observadores) se suscriban a otros (sujetos) para recibir notificaciones cuando ocurre algo relevante.

  • Sujeto: envía notificaciones cuando cambia su estado.

  • Observador: reacciona a esos cambios sin necesidad de consultar constantemente.

Ventaja: ideal para sistemas como HUDs, misiones o logros que deben reaccionar a cambios globales del juego.
Ejemplo: cuando el jugador consigue una moneda, el HUD se actualiza automáticamente sin que el código del jugador tenga que saber cómo funciona la interfaz.