Enhanced Input
Enhanced Input es un complemento propio creado por Epic Games que utilizamos en Parrot. Si estás utilizando la última versión de Unreal Engine 5, debería estar habilitado de forma predeterminada. Puedes comprobar si está habilitado en Editar > Complementos al seleccionar la casilla de verificación.
Enhanced Input reemplaza el sistema de entrada predeterminado de Unreal Engine y es el estándar para el manejo complejo de entradas o la reasignación de controles en tiempo de ejecución. La documentación oficial de Epic Games ofrece una excelente descripción general del sistema, junto con instrucciones para configurar los recursos de entrada.
Conceptos esenciales
Para reforzar la documentación oficial, los conceptos básicos de Enhanced Input que debes comprender son los siguientes:
Acciones de entrada
Contextos de asignación de entradas (IMC)
Modificadores de entradas
Activadores de entradas
Si has utilizado el nuevo sistema de entrada de Unity, estos conceptos te resultarán familiares.
Las acciones de entrada pueden entenderse mejor como «lo que hace la acción que se llevará a cabo en el juego» en un contexto concreto del juego. Por ejemplo, si tu personaje está en un coche, querrás tener acciones de aceleración o frenado.
Los contextos de asignación de entradas también funcionan con este ejemplo. Si el jugador entra o sale del coche, es posible que quieras cambiar la función de determinadas teclas o botones del mando.
Los activadores de entradas impedirán que se activen las acciones a menos que se cumplan todas las condiciones de activación. Por ejemplo, es posible que quieras que el jugador mantenga pulsado un botón durante un periodo de tiempo determinado para activar una acción.
Los modificadores de entradas alteran el valor de la entrada en sí. Las zonas muertas son un modificador de entrada común que se utiliza para suavizar los valores de entrada sin procesar. Enhanced Input resuelve todos estos problemas con una sencilla configuración.
Veamos un ejemplo en Parrot. En Content/Input/Gameplay encontrarás una carpeta llamada Actions y un archivo de recurso IMC_Gameplay. En la carpeta Actions, localiza el recurso IA_Jump.
El tipo de valor aquí es Digital (bool), que indica el tipo de salida de esta acción. Entre los activadores, existen los siguientes tipos:
Pulsado
Soltado
Al observar esta acción de entrada, puedes deducir que cualquier tecla o botón asignado debe activarse al pulsarlo y tener un estado de salida bool. Al soltar el botón se detiene la acción. Otro detalle importante aquí es que tanto los activadores como los modificadores pueden ser anulados por un contexto de asignación de entradas. Echemos un vistazo al contexto de asignación de entradas en el juego para ver cómo funciona la sustitución de modificadores en la práctica.
IA_MoveAxis no tiene ningún activador configurado, por lo que el valor de «Eje X de la palanca izquierda del mando» se leerá inmediatamente cuando se detecte un cambio. Para facilitar los valores de entrada sin procesar, utilizamos un modificador de zona muerta para establecer los límites superior e inferior de entrada.
Un ejemplo en el que no proporcionamos una anulación en el IMC es la asignación de saltos.
Aquí verás que el activador proviene de la propia acción de entrada, por lo que no es necesario definir un activador en la asignación. La configuración también se hereda de la acción, pero puedes ignorarla por ahora, ya que se tratará en la sección de reasignación.
Detectores de eventos de Enhanced Input
Ahora que ya tienes tus recursos configurados, debes realizar algunos ajustes para su uso en tiempo de ejecución. En Parrot, nos vinculamos al subsistema de jugador local de Enhanced Input para configurar nuestros detectores de eventos en BP_ParrotPlayerController. Desde el nodo BeginPlay() añadimos el contexto de asignación para IMC_Gameplay.
El parámetro de prioridad es importante aquí. Los contextos de asignación de entradas se evalúan según su prioridad, así que tenlo en cuenta al crear capas de contextos. Por ahora, solo usarás el contexto del juego.
Toma nota del parámetro Notificar ajustes de usuario activado aquí, ya que será necesario para la reasignación de entradas en tiempo de ejecución más adelante.
Con el contexto de asignación listo, solo queda añadir los nodos de eventos Enhanced Input en las acciones que te interesan. Aquí tienes un ejemplo de salto:
La acción comienza cuando presionas el botón y finaliza cuando lo sueltas. Mira el resto de las acciones de entrada en BP_ParrotPlayerController para ver cómo se procesan otros tipos de entradas. Si lo prefieres, también puedes vincular eventos de entrada en C++, tal y como se explica en la documentación oficial.
Reasignación de entradas en tiempo de ejecución
Enhanced Input tiene la capacidad de reasignar las teclas vinculadas a las acciones de entrada en tiempo de ejecución. Cabe señalar que, aunque esta función se puede utilizar, aún está en fase experimental, por lo que se recomienda tener cuidado al usarla. En Parrot, tenemos una pantalla Vinculaciones de teclas que permite al jugador reasignar las teclas. Para lograrlo, combinamos Enhanced Input con el complemento Common UI de Epic Games para proporcionar los metadatos correctos a los widgets de la pantalla. La configuración habitual de la interfaz de usuario se describe en la documentación Interfaz de usuario, que debes leer antes de continuar. Con ese complemento configurado, también puedes mostrar elementos de la interfaz de usuario específicos de la plataforma.
Para empezar, habilita la configuración de usuario para Enhanced Input en la configuración de nuestro proyecto. Puedes hacerlo en Editar > Configuración del proyecto > Motor > Enhanced Input. Configura los ajustes de la siguiente manera
A continuación, navega hasta un recurso de acción de entrada y ajusta Configuración de teclas asignables al jugador. El campo Nombre debe ser único en todas tus acciones de entrada. Nombre en pantalla y Categoría se localizan en Parrot.
También puedes anular la configuración de teclas asignables al jugador al definir una tecla en un IMC. Para la acción de salto en el IMC de juego, hemos dejado esta configuración como «Heredar configuración de la acción», por lo que no es necesario hacer nada especial aquí.
Verifica que cuando añades tu contexto de asignación de entradas en el blueprint del controlador del jugador, el parámetro Notificar ajustes de usuario se activará.
En la siguiente parte, veremos cómo podemos vincular las acciones de Enhanced Input con Common UI. Cubriremos lo necesario para la reasignación de entradas en Parrot, pero esta documentación es complementaria a la guía oficial de inicio rápido de Common UI.
Para el siguiente paso, creamos un nuevo IMC: IMC_UI_Generic en Content/Input/UI.
Debes configurar el campo Configuración de teclas asignables al jugador en cada acción de entrada y apuntarlo al recurso de datos de metadatos de la interfaz de usuario adecuado. A continuación se muestra un ejemplo de la acción genérica de entrada Aceptar y el propio recurso de metadatos.
Estos IMC y acciones en el juego son necesarios para que la interfaz de usuario común conozca las acciones invocadas por la navegación de la interfaz de usuario. Las acciones genéricas «Aceptar» y «Atrás» son ejemplos claros de esto, ya que el jugador siempre querrá invocarlas cuando navegue por las pantallas de la interfaz de usuario. Definimos estas asignaciones en un blueprint de datos específico de CommonUI que crea clases secundarias desde CommonUIInputData.
A continuación, en Editar > Configuración del proyecto > Configuración de entrada común, establece los datos de entrada en tu blueprint de datos de entrada genéricos.
Una vez configurados los campos importantes, puedes pasar a configurar las pantallas de tus widgets. Empieza con una clase básica ParrotScreen para pantallas estáticas y otra activable para las demás. Las pantallas estáticas serían algo parecido al HUD, donde no tienes que preocuparte por la navegación de la interfaz de usuario. Un ejemplo que se puede activar sería el menú de pausa, ya que necesita saber cuándo se pulsa el botón Atrás y se encuentra en la capa Menú de la disposición del juego.
La jerarquía de pantallas se describe en la documentación Interfaz de usuario, pero a modo de referencia se repite aquí:
En la configuración predeterminada de las pantallas BP, establecemos un contexto de asignación de entradas opcional. Esto se aplica al activar/desactivar el widget y puedes anularlo por clase.
UParrotActivatableScreen tiene una implementación para gestionar acciones posteriores. El detector de eventos IA_UI_GenericBack se define en el grafo de eventos de los blueprints derivados que lo utilizan. También debes marcar la casilla Es un controlador de Volver (Is back handler) en el panel Detalles.
Consulta los comentarios de la clase C++ y del BP para ver cómo se utiliza el patrón Atrás en diferentes widgets de pantalla.
Una vez cubiertas las clases básicas, echa un vistazo a la pantalla de atajos de teclado. WBP_KeyBindingsScreen está en Content/UI/Widgets/Screens. Vale la pena revisar el grafo del evento por tu cuenta para ver cómo se consultan los Ajustes de usuario y el Perfil de teclas para extraer los tipos de asignación de teclas del jugador de Enhanced Input. Los datos se utilizan para añadir y rellenar widgets WBP_InputSelectorBox. Dentro del widget WBP_InputSelectorBox encontrarás dos widgets W_ParrotInputSelector.
Uno se utiliza para las entradas del mando y otro para las entradas del teclado. El Selector de entrada de Parrot es un widget personalizado inspirado en el widget Selector de entrada integrado. Ambos widgets entran en un estado de selección, esperan una entrada y, a continuación, actualizan la pantalla:
Para el ratón y el teclado, trabajamos con el texto devuelto por el subsistema de Enhanced Input y actualizamos la pantalla.
La implementación del mando se basa en Common UI para buscar imágenes específicas del controlador. En este caso, hemos configurado uno para imágenes de Xbox llamado
CommonInput_Gamepad_XboxenContent/Input/UI/Platform. La clase se deriva deUCommonInputBaseControllerData.
A partir de esta clase, puedes asignar teclas de entrada a pinceles con imágenes. A continuación, configura los datos del controlador en Editar > Configuración del proyecto > Configuración de entrada común y luego navega hasta la plataforma.
Una vez conectados esos datos, el resto del trabajo se lleva a cabo en los widgets. Merece la pena echar un vistazo al código y los comentarios de UParrotInputSelector y WBP_InputSelectorBox para ver exactamente cómo se ejecuta la funcionalidad de reasignación utilizando los subsistemas Enhanced Input y Common UI.
La última funcionalidad importante que hay que destacar es cómo se guardan las teclas asignadas. Esto sucede en SaveKeyMappings en WBP_KeyBindingsScreen. Esta función itera sobre todos los widgets del cuadro selector y, a continuación, utiliza las funciones integradas Aplicar configuración y Guardar configuración de los ajustes del usuario. Guardar configuración escribe un archivo de guardado del juego, EnhancedInputUserSettings.sav, en el disco. Se encuentra en Directorio del proyecto > Parrot > Saved-SaveGames.
Si todo se ha configurado correctamente, ¡deberías tener una pantalla de atajos de teclado que funciona!
Es posible que observes que en la esquina inferior derecha hay un widget de acción que se actualiza cuando se reasigna la tecla. El widget es WBP_ParrotGamepadActionWidget y se encuentra en Content/UI/Widgets/Common. Hace un uso intensivo de la clase UCommonActionWidget de Common UI, que está diseñada para mostrar iconos específicos de la plataforma en función de una acción de entrada utilizando los datos de entrada comunes que hemos creado anteriormente. Aprovechando Common UI, es fácil crear nuevos widgets según sea necesario que hagan referencia a las acciones de Enhanced Input de tu juego.