Por qué los flujos de control importan en tu grafo
En Blueprints, el “flujo de control” es la forma en que decides qué camino de ejecución sigue tu lógica. Dominarlo te permite: evitar condiciones duplicadas, controlar cuándo se ejecuta algo (y cuántas veces), recorrer colecciones de forma segura y mantener el grafo legible. En este capítulo verás nodos clave (Branch, Switch, DoOnce, Gate, Sequence, bucles) y patrones prácticos para construir lógica robusta sin caer en “spaghetti”.
Branch: decisiones binarias (Sí/No) sin complicaciones
Branch evalúa un booleano y ejecuta True o False. Úsalo cuando la decisión sea realmente binaria. Si empiezas a encadenar muchos Branch, suele ser señal de que necesitas un Switch (por estados) o una función que encapsule la condición.
Ejemplo típico: validar interacción
- Condición: “¿El jugador está lo suficientemente cerca?”
- Condición: “¿El objeto está bloqueado?”
En lugar de encadenar Branch en línea, es más legible crear una función booleana CanInteract() que devuelva un único booleano y usar un solo Branch en el evento de interacción.
Input Interact -> Branch (CanInteract? ) -> True: DoInteract / False: PlayDeniedFeedbackSwitch: decisiones con múltiples caminos
Cuando tienes más de dos opciones, Switch reduce ramas y mejora la lectura. Los más comunes son Switch on Int, Switch on Name y, especialmente útil para gameplay, Switch on Enum.
Patrón de estado con Enums: Idle / Interact / Locked
Un patrón muy limpio para lógica de interacción es modelar el “estado” con un Enum. Por ejemplo: EInteractState con valores Idle, Interact, Locked. Luego, en el punto de decisión, usas Switch on EInteractState.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
Guía práctica paso a paso: estado de interacción con Switch on Enum
Crea un Enum (por ejemplo
EInteractState) con:Idle,Interact,Locked.En tu Blueprint del objeto interactuable, crea una variable
InteractStatede tipoEInteractState. Define un valor inicial (por ejemploIdle).En el evento de interacción (por ejemplo, cuando recibes la orden de interactuar), conecta a
Switch on EInteractState.Implementa cada pin:
Idle: muestra prompt o prepara interacción (por ejemplo, cambiar aInteract).Interact: ejecuta la acción (abrir, recoger, activar) y luego vuelve aIdleo pasa aLockedsegún el diseño.Locked: reproduce feedback de “bloqueado” (sonido, UI, etc.).
Opcional: encapsula el cambio de estado en una función
SetInteractState(NewState)para centralizar efectos secundarios (por ejemplo, actualizar material, UI, colisión).
Ventaja: el grafo se lee como un diagrama de estados. Si mañana agregas Cooldown o Disabled, solo amplías el Enum y el Switch.
Sequence: ejecutar pasos en orden sin ramificar
Sequence dispara varias salidas en orden (Then 0, Then 1, etc.). Es útil cuando quieres “pasos” claros sin anidar cables.
Uso recomendado
- Separar “validación”, “ejecución” y “feedback” en pasos.
- Evitar que un solo cable se convierta en una autopista con muchas derivaciones.
OnInteract -> Sequence -> Then0: Validate -> Then1: Execute -> Then2: UpdateUISi cada paso crece, conviértelo en función (o macro si necesitas pines de ejecución múltiples).
DoOnce: limitar ejecuciones (con Reset)
DoOnce permite que un flujo pase solo la primera vez; luego bloquea hasta que reciba Reset. Es ideal para evitar spam de interacciones, disparos repetidos de efectos o inicializaciones accidentales.
Ejercicio 1: limitar una interacción con DoOnce + Reset
Objetivo: permitir que un botón se active una sola vez, pero que se pueda rearmar tras cierto evento (por ejemplo, al salir del área o tras un temporizador).
En el evento de interacción, conecta a
DoOnce.En la salida
Completed, ejecuta la acción (por ejemplo, abrir una puerta o activar una luz).Define cuándo se rearma:
- Opción A: al salir del trigger (evento de fin de solapamiento) llama a
Reset. - Opción B: tras un
Delay(por ejemplo 2s) llama aReset. - Opción C: cuando el sistema termine (por ejemplo, puerta vuelve a cerrarse) llama a
Reset.
- Opción A: al salir del trigger (evento de fin de solapamiento) llama a
OnInteract -> DoOnce -> Completed: ActivateButton -> Delay(2.0) -> Reset(DoOnce)Consejo: si el “rearmado” depende de reglas complejas, crea una función RearmInteraction() y llama a Reset desde ahí.
Gate: abrir/cerrar el paso de ejecución
Gate funciona como una compuerta: si está abierta, deja pasar la ejecución; si está cerrada, la bloquea. Tiene entradas típicas: Open, Close, Toggle y Enter. Es excelente para controlar acceso a una acción según condiciones externas, sin recalcularlas cada vez con Branch.
Ejercicio 2: controlar acceso con Gate
Objetivo: permitir interacción solo mientras el jugador está dentro de un área, y bloquearla al salir.
Coloca un volumen/trigger asociado al objeto.
En el evento de inicio de solapamiento (cuando el jugador entra), conecta a
OpendelGate.En el evento de fin de solapamiento (cuando el jugador sale), conecta a
Close.Conecta el evento de interacción a
Enterdel Gate.En la salida del Gate, ejecuta la acción.
OnBeginOverlap(Player) -> Gate.OpenOnEndOverlap(Player) -> Gate.CloseOnInteract -> Gate.Enter -> DoInteractVariación útil: usa Toggle para habilitar/deshabilitar interacción con un interruptor global (por ejemplo, “modo hackeo”).
Bucles: For, ForEach y While (con precaución)
Los bucles te permiten repetir lógica. En Blueprints, es crucial evitar bucles que puedan ejecutarse “sin fin” en un solo frame, porque pueden congelar el juego/editor. En general, prefiere ForEach para colecciones y usa While solo si estás completamente seguro de que terminará rápido y siempre.
For Loop
ForLoop itera desde un índice inicial a uno final. Útil para generar o procesar por índice (por ejemplo, 0..N-1). Si necesitas romper antes de tiempo, usa ForLoopWithBreak.
ForEach Loop
ForEachLoop recorre un array y te da el elemento actual y su índice. Es el patrón más común para procesar colecciones de actores, componentes, ítems de inventario, etc.
Ejercicio 3: procesar una colección con ForEach
Objetivo: al activar un panel, encender varias luces (array) y contar cuántas se encendieron.
Crea una variable array
Lights(por ejemplo, referencias a actores de luz o componentes).En el evento de activación, inicializa un contador
TurnedOnCounta 0.Ejecuta
ForEachLoopsobreLights.En
Loop Body:- Valida el elemento (si puede ser nulo) con
IsValid. - Enciende la luz.
- Incrementa
TurnedOnCount.
- Valida el elemento (si puede ser nulo) con
En
Completed, muestra/usa el contador (por ejemplo, actualizar UI o desbloquear algo si el total supera un umbral).
ActivatePanel -> Set TurnedOnCount=0 -> ForEach(Lights)LoopBody: IsValid? -> True: TurnOnLight -> TurnedOnCount++Completed: CheckIfAllOn(TurnedOnCount)Consejo: si el cuerpo del bucle crece, muévelo a una función ProcessLight(LightRef) para mantener el grafo legible.
While Loop (usar con precaución)
WhileLoop repite mientras una condición sea verdadera. El riesgo es que, si la condición nunca cambia a falso, el juego se quedará bloqueado. En Blueprints, muchas tareas “repetitivas en el tiempo” se resuelven mejor con temporizadores o lógica por ticks controlados, en lugar de While.
| Necesidad | Mejor opción | Evitar |
|---|---|---|
| Reintentar algo a lo largo del tiempo | Timer / eventos | While en un solo frame |
| Procesar un array | ForEach | While manual con índice |
| Buscar hasta encontrar | ForLoopWithBreak | While sin límite |
Si aun así usas While, añade un “límite de seguridad” (contador máximo) para garantizar salida.
Macros útiles para mantener el grafo limpio
Las macros son ideales para empaquetar patrones repetidos de flujo de control, especialmente cuando necesitas múltiples pines de ejecución o quieres reutilizar “mini-estructuras” en varios lugares. Úsalas para reducir cables y mejorar la lectura, pero evita meter demasiada lógica de negocio dentro: una macro debería ser pequeña y predecible.
Macro: Guard Clause (salida temprana)
Patrón: si no se cumple una condición, sal inmediatamente. Esto evita anidar Branch dentro de Branch.
Exec -> Branch(Condition) -> False: Return/Stop | True: ContinueEn macro, puedes exponer: Exec In, Condition, Exec Out y opcionalmente Exec Failed para feedback.
Macro: Validate + Execute
Patrón: validar referencias y estado antes de ejecutar. Útil cuando repites IsValid + checks en muchos sitios.
Lectura del grafo: cómo evitar “spaghetti”
Reglas prácticas de diseño
Responsabilidad única por bloque: un bloque del grafo debería hacer una cosa (validar, ejecutar, actualizar UI), no todo a la vez.
Divide en funciones cuando la lógica produce un resultado (por ejemplo,
CanInteract(),GetCurrentState(),ComputeScore()).Usa macros cuando el valor está en el flujo (por ejemplo, guard clauses, secuencias repetidas, compuertas).
Evita cables largos: reordena nodos, usa
Reroutey agrupa por secciones.Nombra claramente: variables como
InteractState,bHasKey,RemainingUseshacen que el Branch se lea solo.
Ejemplo de refactor: de Branch encadenados a Switch por estado
Si tu interacción tiene varios “modos” (bloqueado, en uso, listo, en cooldown), un árbol de Branch se vuelve difícil de mantener. Cambia a:
- Un Enum de estado.
- Un
Switch on Enumcomo punto central. - Funciones pequeñas por caso:
HandleIdle(),HandleInteract(),HandleLocked().
OnInteract -> Switch(InteractState) -> Idle: HandleIdle() | Interact: HandleInteract() | Locked: HandleLocked()