Variables, referencias y comunicación entre Blueprints

Capítulo 4

Tiempo estimado de lectura: 10 minutos

+ Ejercicio

Variables en Blueprints: tipos, organización y exposición

Una variable es un dato que tu Blueprint guarda y usa para tomar decisiones o modificar el comportamiento. Elegir el tipo correcto y exponerlo bien (para edición o para acceso desde otros Blueprints) reduce errores y hace tu proyecto más escalable.

Tipos de variables más usados (y cuándo elegirlos)

  • Boolean (bool): estados binarios (abierto/cerrado, encendido/apagado).
  • Integer (int): contadores, índices, cantidades discretas.
  • Float: valores continuos (velocidad, tiempo, interpolaciones).
  • Vector: posiciones, direcciones, escalas.
  • Rotator: rotaciones (yaw/pitch/roll).
  • String / Name: identificadores y texto. Name suele ser mejor para etiquetas y comparaciones.
  • Enum: estados con múltiples opciones (por ejemplo: Closed, Opening, Open, Closing).
  • Object Reference: referencia a otro objeto/actor (por ejemplo, una puerta específica).
  • Class Reference: referencia a una clase (para spawnear o filtrar tipos).

Crear variables con valores por defecto, categorías y tooltips

En el panel My Blueprint crea una variable y configura:

  • Default Value: el valor inicial que tendrá el Blueprint (útil para prototipado y comportamiento estándar).
  • Category: agrupa variables en el panel de detalles (por ejemplo: Door, Switch, Debug).
  • Tooltip: describe qué hace y unidades (por ejemplo: Velocidad de apertura en grados/segundo).

Convención práctica: usa nombres claros y consistentes, por ejemplo bIsOpen (bool), OpenSpeed (float), TargetDoor (Door reference).

Exponer variables: Instance Editable y Blueprint Read/Write

Hay dos necesidades comunes: editar valores desde el editor por instancia, y permitir que otros Blueprints lean/escriban el valor.

  • Instance Editable: permite modificar la variable en el panel Details de cada instancia colocada en el nivel. Útil para ajustar OpenSpeed por puerta o asignar una referencia específica.
  • Blueprint Read Only / Read Write: controla si otros Blueprints pueden leer o modificar la variable cuando tienen una referencia a este actor. Útil para exponer estado (bIsOpen) o permitir configuración desde fuera.

Recomendación: por defecto, mantén variables internas como privadas (no expuestas) y expón solo lo necesario. Si necesitas que otros Blueprints cambien algo, considera crear funciones (por ejemplo OpenDoor()) en lugar de permitir escritura directa.

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

Referencias: cómo obtener y guardar actores

Una referencia es “un puntero” a un actor u objeto existente. Sin referencia, no puedes llamar funciones ni leer variables del otro Blueprint. En gameplay, las referencias suelen obtenerse de tres formas: por eventos de colisión/overlap, por búsqueda (tag/clase), o asignándolas desde el editor.

1) Obtener referencias mediante colisión/overlap

Escenario típico: un interruptor detecta al jugador cuando entra en un área.

  • Agrega un componente de colisión (por ejemplo Box Collision) al actor.
  • Usa el evento OnComponentBeginOverlap.
  • Del pin Other Actor obtienes una referencia al actor que entró.

Buenas prácticas:

  • Filtra por tipo antes de usar la referencia (por ejemplo, comprobar si es el jugador).
  • Guarda la referencia en una variable solo si la necesitas después (por ejemplo OverlappingActor).

2) Buscar actores por etiqueta (Actor Tags)

Útil cuando quieres encontrar actores en el nivel sin asignarlos manualmente, pero sin depender de un nombre específico.

  • En el actor objetivo (por ejemplo la puerta), añade una etiqueta en Details > Actor > Tags, por ejemplo Door_A.
  • En el Blueprint que busca, usa Get All Actors with Tag.
  • Selecciona el primer elemento del array (si esperas uno) y guárdalo en una variable de referencia.

Precaución: Get All Actors... puede ser costoso si lo llamas frecuentemente. Úsalo en inicialización (por ejemplo al comenzar) o cuando sea necesario, no cada frame.

3) Asignación desde el editor (la forma más limpia para niveles diseñados a mano)

Cuando el diseñador coloca un interruptor y una puerta concretos, lo más robusto es exponer una variable de referencia y asignarla en el editor.

  • Crea una variable TargetDoor del tipo BP_Door Object Reference (o mejor, una interfaz; lo veremos más abajo).
  • Activa Instance Editable (y opcionalmente Expose on Spawn si se crea por spawn).
  • En el nivel, selecciona el interruptor y en Details asigna la puerta arrastrándola desde el World Outliner.

Ventaja: evita búsquedas, es explícito y fácil de depurar.

Comunicación entre Blueprints

Una vez que tienes una referencia, necesitas un mecanismo para comunicar intención: “abre”, “cierra”, “cambia velocidad”, “notifica evento”. Hay tres herramientas clave: casting, interfaces y dispatchers.

Casting básico (rápido, pero crea dependencia)

Cast To BP_Door intenta tratar una referencia genérica (por ejemplo Other Actor) como un tipo específico. Si el objeto realmente es de ese tipo, el cast tiene éxito y puedes acceder a sus funciones/variables.

Ejemplo típico: en un overlap, haces cast del Other Actor a BP_Player para confirmar que es el jugador.

  • Pros: simple y directo.
  • Contras: dependencia fuerte (el Blueprint “conoce” el tipo exacto). Si cambias la clase, debes actualizar casts.

Blueprint Interfaces (comunicación sin dependencia fuerte)

Una Blueprint Interface define un “contrato” de funciones que cualquier Blueprint puede implementar. El emisor no necesita saber la clase exacta del receptor; solo necesita que implemente la interfaz.

Cuándo usarla: cuando varios tipos de actores podrían responder a la misma acción (puertas, luces, plataformas) o cuando quieres desacoplar interruptores de puertas específicas.

Crear e implementar una interfaz

  • Crea una interfaz: BPI_Interactable o específica: BPI_DoorControl.
  • Define una función, por ejemplo SetDoorState con parámetros: bOpen (bool), Speed (float).
  • En BP_Door, en Class Settings agrega la interfaz.
  • Implementa el evento/función de la interfaz dentro de BP_Door y aplica la lógica (abrir/cerrar).

En el emisor (interruptor), usa el nodo de llamada de interfaz (por ejemplo SetDoorState (Message)) sobre una referencia. Si el actor no implementa la interfaz, no pasa nada (fallo seguro).

Event Dispatchers (eventos, suscripción y múltiples oyentes)

Un Dispatcher es un evento que un Blueprint “emite” y otros Blueprints pueden “escuchar” (bind). Es ideal para notificar cambios sin que el emisor llame directamente a una función concreta del receptor.

Cuándo usarlo: cuando un evento puede interesar a varios oyentes (una puerta, una luz, un sonido, un UI), o cuando quieres un patrón tipo “publicador/suscriptor”.

Conceptos clave

  • Declare: creas el dispatcher en el emisor (por ejemplo OnSwitchToggled).
  • Bind: el receptor se suscribe (por ejemplo la puerta se bindea al dispatcher del interruptor).
  • Broadcast: el emisor dispara el evento y todos los suscritos reaccionan.

Los dispatchers pueden tener parámetros (por ejemplo bIsOn, Speed), lo que los hace perfectos para enviar datos junto con el evento.

Mini-proyecto: Interruptor y puerta (interfaz o dispatcher)

Objetivo: crear un BP_Switch que al activarse notifique a BP_Door para abrir/cerrar. Debe enviar parámetros como Speed y bOpen. Se proponen dos variantes: con interfaz (más directo y desacoplado) o con dispatcher (event-driven y con múltiples oyentes).

Preparación: BP_Door (variables y estructura)

Variables recomendadas

  • bIsOpen (bool): estado actual. Tooltip: Indica si la puerta está abierta. Categoría: Door|State. Exposición: Blueprint Read Only (normalmente).
  • OpenSpeed (float): velocidad por defecto. Categoría: Door|Config. Exposición: Instance Editable (para ajustar por instancia).
  • OpenYaw (float): ángulo objetivo de apertura (por ejemplo 90). Categoría: Door|Config. Instance Editable.

Lógica de movimiento (simplificada)

Implementa una función ApplyDoorState(bOpen, Speed) que:

  • Actualiza bIsOpen.
  • Calcula el yaw objetivo (0 si cierra, OpenYaw si abre).
  • Interpola la rotación del componente de la puerta (por ejemplo con Timeline o con interpolación en tick si ya lo tienes montado).

Ejemplo de firma (pseudo):

Function ApplyDoorState(bool bOpen, float SpeedOverride) -> void

Nota: si SpeedOverride es menor o igual a 0, puedes usar OpenSpeed como fallback.

Variante A: Comunicación con Blueprint Interface (recomendada para desacoplar)

Paso 1: Crear la interfaz

  • Crea BPI_DoorControl.
  • Agrega función SetDoorState con parámetros: bOpen (bool), Speed (float).

Paso 2: Implementar en BP_Door

  • En BP_Door agrega la interfaz en Class Settings.
  • Implementa SetDoorState y dentro llama a ApplyDoorState(bOpen, Speed).

Paso 3: Configurar BP_Switch (variables y edición)

En BP_Switch crea:

  • bIsOn (bool): estado del interruptor. Categoría: Switch|State. Read Only para otros (opcional).
  • DoorTarget (Object Reference): tipo Interface (BPI_DoorControl). Categoría: Switch|Links. Instance Editable para asignar desde el editor.
  • DoorSpeed (float): velocidad enviada a la puerta. Categoría: Switch|Config. Instance Editable. Tooltip: Velocidad enviada a la puerta; 0 usa la velocidad por defecto de la puerta.

Importante: al usar una variable de tipo interfaz, puedes asignar cualquier actor que implemente esa interfaz (no solo una clase concreta).

Paso 4: Activación del interruptor y envío del mensaje

  • Cuando el jugador interactúe (por ejemplo por overlap + input, o un evento de interacción ya existente en tu proyecto), invierte bIsOn.
  • Decide el estado de puerta: por ejemplo bOpen = bIsOn.
  • Llama SetDoorState (Message) sobre DoorTarget con bOpen y DoorSpeed.

Si DoorTarget no está asignado, el mensaje no hará nada; aun así, conviene validar con Is Valid para depuración.

Variante B: Comunicación con Event Dispatcher (ideal para múltiples oyentes)

Paso 1: Crear dispatcher en BP_Switch

En BP_Switch crea un dispatcher:

  • OnSwitchToggled con parámetros: bIsOn (bool), Speed (float).

Paso 2: Emitir el evento

  • Al activar el interruptor, actualiza bIsOn.
  • Llama OnSwitchToggled.Broadcast pasando bIsOn y DoorSpeed.

Paso 3: Hacer que la puerta se suscriba (Bind)

Necesitas que la puerta tenga una referencia al interruptor (asignada desde el editor o encontrada por tag/overlap). En BP_Door:

  • Crea variable SwitchSource de tipo BP_Switch Object Reference (o una clase base de interruptor si la tienes). Marca Instance Editable.
  • En un punto de inicialización (por ejemplo al comenzar), si SwitchSource es válido, usa Bind Event to OnSwitchToggled.
  • Crea un evento manejador (custom event) que reciba bIsOn y Speed, y llame a ApplyDoorState(bIsOn, Speed).

Ventaja: puedes tener varias puertas escuchando al mismo interruptor, o un interruptor que notifica a puerta + luz + sonido sin que el interruptor conozca sus clases.

Asignación y pruebas en el nivel (para ambas variantes)

  1. Coloca una instancia de BP_Door y una de BP_Switch en el nivel.
  2. Ajusta en la puerta: OpenYaw y OpenSpeed (Instance Editable).
  3. Si usas interfaz: en el interruptor asigna DoorTarget apuntando a la puerta.
  4. Si usas dispatcher: en la puerta asigna SwitchSource apuntando al interruptor.
  5. Ajusta DoorSpeed en el interruptor para probar overrides (por ejemplo 0 para usar default, o 120 para abrir más rápido).
  6. Ejecuta y activa el interruptor: verifica que el estado y la velocidad se transmiten correctamente.

Tabla rápida: ¿Casting, Interfaz o Dispatcher?

MecanismoCuándo usarDependenciaSoporta múltiples receptores
CastingCuando necesitas un tipo exacto y control directoAltaNo (normalmente 1 a 1)
InterfaceCuando quieres llamar acciones sin conocer la clase concretaBaja1 a 1 por llamada (puedes llamar a varios si tienes referencias)
DispatcherCuando quieres emitir eventos y que otros se suscribanMedia-baja (según cómo obtengas la referencia)

Errores comunes y cómo evitarlos

  • Referencias nulas (None): si una variable no está asignada, cualquier acceso fallará. Usa Is Valid y tooltips claros indicando que debe asignarse.
  • Buscar actores constantemente: evita llamar Get All Actors... repetidamente. Guarda la referencia una vez.
  • Exponer demasiado: no marques todo como Blueprint Read/Write. Expón solo lo que de verdad debe configurarse o consultarse.
  • Acoplamiento excesivo por casting: si notas muchos Cast To ... entre sistemas, considera migrar a interfaces o dispatchers.

Ahora responde el ejercicio sobre el contenido:

En un nivel diseñado a mano, ¿cuál es la forma más robusta y fácil de depurar para conectar un interruptor con una puerta específica sin realizar búsquedas en tiempo de ejecución?

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

¡Tú error! Inténtalo de nuevo.

La asignación desde el editor mediante una referencia Instance Editable evita búsquedas costosas, es explícita y facilita la depuración al enlazar directamente la puerta correcta por instancia.

Siguiente capítulo

Flujos de control y estructuras de decisión en Blueprints

Arrow Right Icon
Portada de libro electrónico gratuitaUnreal Engine para Principiantes: Fundamentos de Blueprints y Lógica de Gameplay
36%

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.