Proyecto integrador de Unreal Engine: prototipo jugable basado en Blueprints

Capítulo 11

Tiempo estimado de lectura: 9 minutos

+ Ejercicio

Objetivo del proyecto integrador

Vas a construir un prototipo jugable pequeño (vertical slice) que conecte sistemas típicos de gameplay en un solo nivel: un objetivo claro, interacción por trazado (trace), coleccionables con contador, un obstáculo que cause daño y una condición de victoria/derrota. La meta no es “hacerlo grande”, sino hacerlo coherente, testeable y bien comunicado entre Blueprints.

Reglas de diseño para este capítulo

  • Comunicación coherente entre Blueprints usando Blueprint Interfaces y/o Event Dispatchers (evita casts en cadena).
  • Evitar lógica innecesaria en Tick. Solo usarlo si es imprescindible (y con un motivo claro).
  • Validar con pruebas: casos normales y bordes (sin objetivos, múltiples pickups, reinicio).

Arquitectura mínima (qué Blueprints vas a crear)

Para mantener el proyecto ordenado, usa estos actores/clases (nombres sugeridos):

  • BP_PlayerCharacter: movimiento ya existente + interacción + salud.
  • BP_PlayerController (opcional): si prefieres centralizar input de interacción.
  • BP_GameMode: reglas del nivel (victoria/derrota) y spawn.
  • BP_GameState o BP_PlayerState: estado replicable/central (contador de pickups, objetivo). En singleplayer puedes usar GameState igualmente por claridad.
  • WBP_HUD: UI en juego (salud, pickups, objetivo).
  • WBP_EndScreen: pantalla de victoria/derrota con reinicio.
  • BP_Pickup: coleccionable.
  • BP_Hazard: obstáculo que daña (por overlap).
  • BP_Goal: zona/actor de finalización (requiere X pickups).
  • BPI_Interactable: interfaz para interactuar.

Nota de coherencia: el jugador solo “sabe” que algo es interactuable si implementa BPI_Interactable. El resto de lógica (sumar pickups, validar victoria) se decide en un lugar central (GameMode/GameState), no en el pickup.

Entregable 1: Configuración del nivel (layout y objetivos)

Paso a paso

  • Crea un nivel pequeño con un camino claro: inicio → pickups → obstáculo → meta.
  • Coloca 3–10 pickups visibles y una zona de meta (BP_Goal).
  • Coloca 1–3 hazards (BP_Hazard) en puntos donde el jugador deba esquivar.
  • Añade un PlayerStart y asegúrate de que el GameMode del nivel sea tu BP_GameMode.

Variables de diseño recomendadas

ElementoVariableEjemplo
BP_GameModeRequiredPickups5
BP_PlayerCharacterMaxHealth, Health100
BP_HazardDamageAmount, DamageCooldown25, 0.5

Evita Tick: el nivel no necesita lógica por frame. Todo debe dispararse por eventos (overlap, interacción, cambios de estado).

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

Entregable 2: Personaje (salud y eventos de daño)

El personaje debe poder recibir daño, actualizar UI y disparar derrota al llegar a 0.

Paso a paso (BP_PlayerCharacter)

  • Agrega variables: MaxHealth (float/int), Health.
  • En BeginPlay: set Health = MaxHealth.
  • Crea un Event Dispatcher en el personaje: OnHealthChanged(CurrentHealth, MaxHealth).
  • Crea una función ApplyDamageSimple(DamageAmount) que:
    • Reste vida con clamp a 0.
    • Llame OnHealthChanged.
    • Si Health == 0, notifique derrota al sistema central (GameMode) con una llamada clara (por ejemplo, una función en GameMode: RequestDefeat).

Comunicación recomendada: el personaje no debería crear UI ni decidir pantallas; solo reporta su estado. El GameMode decide el final de partida.

Entregable 3: Sistema de interacción con trazado (trace) + interfaz

La interacción será “mirar y presionar interactuar”. No uses Tick para “escaneo continuo” si no lo necesitas; puedes trazar solo cuando el jugador presiona el botón, o trazar a intervalos con un Timer si quieres resaltar objetos.

Crear la interfaz BPI_Interactable

Crea BPI_Interactable con estas funciones:

  • CanInteract(Interactor) -> bool
  • Interact(Interactor)
  • GetInteractText() -> Text (opcional para UI)

Paso a paso (trazado al presionar)

  • En BP_PlayerCharacter (o Controller), crea una acción de input “Interact”.
  • Al presionar:
    • Obtén la cámara (o el punto de vista) y calcula Start y End (distancia 200–400).
    • Haz un LineTraceByChannel (o SphereTrace si quieres tolerancia).
    • Si hay hit: toma Hit Actor y verifica Does Implement Interface (BPI_Interactable).
    • Si implementa: llama CanInteract. Si true, llama Interact pasando self como Interactor.
// Pseudoflujo en Blueprints (conceptual) Input Interact -> GetViewLocation/Rotation -> LineTrace -> HitActor -> Implements BPI_Interactable? -> CanInteract(self) -> Interact(self)

Evita casts: no hagas “Cast to BP_Pickup” desde el jugador. Si mañana agregas una puerta, no quieres tocar el jugador.

Entregable 4: Pickups + contador central

El pickup debe ser interactuable y, al recogerse, debe incrementar un contador global del nivel. Ese contador alimenta la UI y la condición de victoria.

Estado del contador: ¿GameState o PlayerState?

  • Singleplayer: puedes guardar CollectedPickups en GameState para que sea accesible desde UI y otros actores.
  • Si planeas multijugador luego: PlayerState es mejor para contadores por jugador.

En este prototipo, usa BP_GameState con:

  • CollectedPickups (int)
  • Event Dispatcher: OnPickupsChanged(NewValue)

BP_Pickup (implementa BPI_Interactable)

  • Componentes: StaticMesh + Collision (para que se pueda apuntar/tracear).
  • Variables: PickupValue (int, default 1), bConsumed (bool).
  • CanInteract: retorna !bConsumed.
  • Interact:
    • Si ya consumido, return.
    • Marca bConsumed = true.
    • Llama a una función del GameState: AddPickups(PickupValue).
    • Desactiva colisión y oculta el mesh, o destruye el actor.

BP_GameState: función AddPickups

  • AddPickups(Amount): suma, actualiza CollectedPickups, dispara OnPickupsChanged.

Detalle importante: el pickup no decide victoria. Solo reporta “se recogió”. La regla “cuántos necesito” vive en GameMode.

Entregable 5: Obstáculo que causa daño (hazard) sin spam

El hazard dañará por superposición, pero debe evitar “daño por frame” incontrolado. Implementa un cooldown por actor que entra.

BP_Hazard (daño por overlap con cooldown)

  • Componentes: Collision (Box/Sphere) + Mesh (opcional).
  • Variables: DamageAmount, DamageCooldown.
  • Estructura: un Map de Actor -> LastDamageTime (o un Set de actores en cooldown con Timer).
  • En OnComponentBeginOverlap:
    • Si OtherActor es el jugador (o implementa una interfaz de “Damageable” si quieres extender): aplica daño si no está en cooldown.
    • Registra el tiempo y/o programa un Timer para permitir daño de nuevo.
// Idea de cooldown (conceptual) OnOverlap(Player): if Now - LastDamageTime[Player] >= DamageCooldown: Player.ApplyDamageSimple(DamageAmount); LastDamageTime[Player]=Now

Evita Tick: no uses Tick para revisar overlaps. Overlap events + cooldown resuelven el problema.

Entregable 6: UI (HUD) conectada por eventos, no por polling

La UI debe reaccionar a cambios (vida, pickups) en lugar de consultar valores cada frame.

WBP_HUD: elementos mínimos

  • Texto o barra de vida.
  • Texto de pickups: Collected / Required.
  • Texto de objetivo (opcional): “Recolecta X y llega a la meta”.

Conexión recomendada (event-driven)

  • En BP_PlayerController o BP_PlayerCharacter en BeginPlay: crea el widget HUD y añádelo al viewport.
  • Suscribe el HUD a:
    • PlayerCharacter.OnHealthChanged
    • GameState.OnPickupsChanged
  • Cuando se disparen, el HUD actualiza sus textos/barras.

Consejo: si el HUD necesita RequiredPickups, léelo desde GameMode (o expón una variable en GameState inicializada por GameMode al comenzar).

Entregable 7: Condición de victoria/derrota + pantalla final

La victoria ocurre cuando el jugador llega a la meta y tiene suficientes pickups. La derrota ocurre cuando la vida llega a 0. Ambas deben terminar en una pantalla final con opción de reiniciar.

BP_Goal (meta interactiva o por overlap)

Tienes dos opciones:

  • Opción A (por overlap): al entrar en la zona, se evalúa si cumple requisitos.
  • Opción B (por interacción): el jugador debe presionar interactuar en la meta (útil para mostrar “Te faltan X”).

Recomendación: Opción B usando BPI_Interactable, así reutilizas el sistema de interacción.

BP_Goal implementando BPI_Interactable

  • CanInteract: true si el interactor es el jugador (o siempre true).
  • Interact:
    • Obtén CollectedPickups del GameState.
    • Obtén RequiredPickups del GameMode (o GameState).
    • Si cumple: llama a GameMode RequestVictory.
    • Si no cumple: opcionalmente dispara un mensaje UI (por ejemplo, un dispatcher en HUD o un “toast” simple).

BP_GameMode: control del fin de partida

  • Variables: bGameEnded (bool).
  • Funciones: RequestVictory, RequestDefeat.
  • En cada función:
    • Si bGameEnded, return (evita dobles finales).
    • Set bGameEnded = true.
    • Crear y mostrar WBP_EndScreen con un estado (Victory/Defeat).
    • Deshabilitar input del jugador o cambiar a UI Only.

WBP_EndScreen

  • Texto grande: “Victoria” o “Derrota” (sin depender de Tick).
  • Botón “Reiniciar”: llama a OpenLevel con el nombre del nivel actual.
  • Botón “Salir” (opcional): QuitGame.

Reinicio limpio: al reiniciar con OpenLevel, el estado se reconstruye. Asegúrate de que el contador se inicialice en 0 en BeginPlay del GameState o al iniciar el nivel (por ejemplo, GameMode lo setea).

Pruebas: casos normales y bordes (checklist)

Casos normales

  • Recolectar 1 pickup incrementa el contador y actualiza HUD.
  • Recibir daño reduce vida y actualiza HUD.
  • Con pickups suficientes, interactuar con la meta muestra victoria.
  • Con vida 0, se muestra derrota y se bloquea el control.

Casos borde

  • Sin objetivos/pickups en el nivel:
    • Si RequiredPickups es 0, la meta debe permitir victoria inmediata.
    • Si RequiredPickups > 0 pero no hay pickups colocados, el juego debe seguir funcionando (solo no se podrá ganar). Considera mostrar “Faltan X” al interactuar con la meta.
  • Múltiples pickups recogidos rápido:
    • Verifica que no se duplique el conteo por doble interacción (usa bConsumed y desactiva colisión/actor).
  • Daño en hazard:
    • Permanece dentro del hazard: el cooldown debe evitar que la vida caiga a 0 instantáneamente.
    • Entrar/salir repetidamente: el daño debe ser consistente.
  • Reinicio:
    • Tras reiniciar, vida vuelve a Max y pickups vuelven a 0.
    • La pantalla final no debe persistir.

Mejoras opcionales (mismo proyecto, solo Blueprints)

  • Checkpoint: guarda un transform al pasar por un trigger; al morir, respawnea ahí en lugar de reiniciar el nivel.
  • Sonidos: SFX al recoger pickup, recibir daño, victoria/derrota (Audio Component o Play Sound at Location).
  • Efectos visuales básicos:
    • Pickup: rotación suave con Timeline (en lugar de Tick) o material emissive.
    • Daño: flash en pantalla (UMG) o cambio breve de material en el personaje.
  • Resaltado de interactuables: al mirar un objeto, mostrar outline o cambiar material; implementa un Timer que trace cada 0.1s en lugar de Tick.
  • Mensajes de objetivo: un widget pequeño tipo “toast” que diga “Te faltan X pickups” al intentar la meta.

Ahora responde el ejercicio sobre el contenido:

¿Cuál enfoque respeta mejor la arquitectura recomendada para que el jugador pueda interactuar con diferentes objetos (por ejemplo, pickups y meta) sin depender de casts específicos?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

La solución recomendada es desacoplar al jugador usando una interfaz: el trace detecta el actor, se valida que implemente BPI_Interactable y se llama a sus funciones. Las reglas globales (contador y victoria/derrota) deben decidirse en GameMode/GameState, evitando casts en cadena y lógica en Tick.

Portada de libro electrónico gratuitaUnreal Engine para Principiantes: Fundamentos de Blueprints y Lógica de Gameplay
100%

Unreal Engine para Principiantes: Fundamentos de Blueprints y Lógica de Gameplay

Nuevo curso

11 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.