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 por defecto. Puedes comprobar si está habilitado dirigiéndote a Editar > Complementos y marcando la casilla.
Enhanced Input reemplaza el sistema de entrada predeterminada de Unreal Engine y es el estándar para el manejo complejo de entradas o para la reasignación de controles en tiempo de ejecución. La documentación oficial de Epic Games ofrece una excelente descripción del sistema y de cómo configurar tus recursos de entrada.
Conceptos básicos
Para reforzar la documentación oficial, los conceptos básicos de Enhanced Input que debes comprender son los siguientes:
Acciones de entrada
Contextos de asignaciones de entrada (IMC)
Modificadores de entrada
Activadores de entrada
Si has usado el nuevo sistema de entradas de Unity, estos conceptos te deberían resultar conocidos.
Las acciones de entrada pueden entenderse mejor como "lo que hace la acción que será realizada en el juego" en un contexto concreto del juego. Por ejemplo, si tu personaje está en un coche, querrás tener las acciones "Acelerar" o "Frenar".
Los contextos de asignaciones de entrada también funcionan con este ejemplo. Si el jugador entra o sale del coche, tal vez quieras cambiar lo que hacen ciertas teclas o botones del mando.
Los activadores de entrada impedirán que se activen acciones a menos que se cumplan todas las condiciones de activación. Por ejemplo, tal vez quieras que el jugador mantenga presionado un botón durante un 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 usa para suavizar valores de entrada sin procesar. Enhanced Input resuelve todos estos problemas con unos pocos ajustes.
Veamos un ejemplo en Parrot. En Content/Input/Gameplay encontrarás la carpeta Actions y el archivo de recurso IMC_Gameplay. En la carpeta Actions, encuentra el recurso IA_Jump.
El tipo de valor es Digital (bool), que indica el tipo de salida de esta acción. En los activadores, se encuentran los siguientes tipos:
Pulsado
Soltado
Al observar esta acción de entrada, puedes ver que la tecla o botón asignado debe activarse al ser pulsado y debe tener un estado de salida booleano. Al soltar el botón, se activa el fin de la acción. Otro detalle importante es que ambos activadores y modificadores pueden ser anulados por un contexto de asignación de entrada. Echemos un vistazo al contexto de asignación de entrada en el juego para ver en práctica la anulación de modificadores.
IA_MoveAxis no tiene asignado ningún activador, así que el valor del eje X de la palanca izquierda del mando será leído inmediatamente cuando se detecte un cambio. Para suavizar los valores de entrada sin procesar, usamos un modificador de zona muerta para establecer los límites de entrada superior e inferior.
Un ejemplo donde no usamos una anulación en el IMC es la asignación de salto.
Aquí verás que el activador viene desde la acción de entrada en sí, por lo que no hace falta definir un activador en la asignación. La configuración también se hereda de la acción, pero por ahora puedes ignorarla, ya que esto se tratará en la sección de reasignación.
Oyentes de eventos de Enhanced Input
Ahora que has configurado tus recursos, necesitas hacer algunos ajustes para el uso en tiempo de ejecución. En Parrot, nos vinculamos al subsistema de jugador local de Enhanced Input para configurar nuestros oyentes de eventos en BP_ParrotPlayerController. Desde el nodo BeginPlay() añadimos el contexto de asignación para IMC_Gameplay.
Aquí es importante el parámetro de prioridad. Los contextos de asignación de entrada son evaluados por su prioridad, así que ten en cuenta eso al momento de crear capas de contextos. Por ahora, solo utilizarás el contexto del juego.
Presta atención al parámetro Notificar la configuración del usuario establecido en verdadero. Esto será necesario más tarde para la reasignación de entrada en tiempo de ejecución.
Con el contexto de asignación listo, lo único que queda es añadir los nodos de evento de entrada mejorada a las acciones que te interesan. Mira el siguiente ejemplo para el salto:
La acción comienza cuando el jugador presiona el botón y se completa cuando suelta el botón. Mira las demás acciones de entrada en BP_ParrotPlayerController para ver cómo son procesados los otros tipos de entrada. Puedes también vincular eventos de entrada en C++ si así lo prefieres. Esto está explicado en la documentación oficial.
Reasignación de entradas en tiempo de ejecución
Enhanced Input tiene la capacidad de reasignar vinculaciones de teclas a acciones de entrada en tiempo de ejecución. Hay que tener en cuenta que, si bien esta función puede utilizarse, aún se encuentra en fase experimental, por lo que se recomienda tener cuidado al usar. En Parrot tenemos la pantalla Vinculaciones de teclas, que permite al jugar reasignar sus teclas. Para esto, emparejamos Enhanced Input con el complemento Common UI de Epic Games para proporcionar los metadatos adecuados a los widgets de la pantalla. La configuración de Common UI se explica en la documentación Interfaz de usuario para Parrot. Se recomienda leer esa sección antes de proceder. Con el complemento configurado, puedes mostrar elementos de la interfaz de usuario específicos de la plataforma.
Para empezar, habilita los ajustes de usuario para Enhanced Input en nuestros ajustes del proyecto. Esto se encuentra en Editar > Ajustes del proyecto > Motor > Enhanced Input. Configura los ajustes de la siguiente manera:
A continuación, dirígete a un recurso de acción de entrada y ajusta Ajustes de teclas asignables del jugador. El campo Nombre debe ser único en todas tus acciones de entrada. Nombre para mostrar y Categoría se encuentran en Parrot.
También puedes anular los ajustes de teclas asignables del jugador al momento de definir una tecla en un IMC. Para la acción de salto en el IMC del juego, dejamos este ajuste como "Heredar configuración desde acción", así que no es necesario hacer nada especial aquí.
Verifica que cuando añadas tu contexto de asignación de entrada en el blueprint del controlador de jugador, el parámetro Notificar ajustes de usuario esté establecido en verdadero.
A continuación veremos cómo emparejar acciones de Enhanced Input con Common UI. Veremos los requerimientos 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 hemos creado un nuevo IMC: IMC_UI_Generic en Content/Input/UI.
Necesitas configurar el campo Ajustes de teclas asignables del jugador para cada acción de entrada y apuntarlo al recurso de datos de metadatos de interfaz de usuario apropiado. A continuación se muestra un ejemplo de la acción de entrada genérica Aceptar y el recurso de metadatos.
Estos IMC y acciones de entrada son necesarios para que Common UI sepa qué acciones son invocadas por la navegación de interfaz de usuario. Las acciones de entrada genéricas de Aceptar y Atrás son ejemplos claros de esto, ya que un jugador siempre querrá invocarlas cuando navegue por pantallas de interfaz de usuario. Definimos estas asignaciones en un blueprint de datos específicos de CommonUI que es una subclase de CommonUIInputData.
Luego, en Editar > Ajustes del Proyecto > Ajustes de entrada común, establece los datos de entrada a tu blueprint de datos de entrada genéricos.
Con los campos importantes configurados, puedes ahora configurar tus pantallas de widgets. Comienzas con una clase básica Pantalla de Parrot para pantallas estáticas y con una activable para las demás. Las pantallas estáticas son algo como el HUD, donde no hay que preocuparse por la navegación de interfaz de usuario. Un ejemplo de una activable es el menú de pausa, ya que necesita saber cuándo se presiona el botón atrás y existe en la capa de menú en la disposición del juego.
La jerarquía de pantallas se detalla en la documentación de Interfaz de usuario para Parrot, pero aquí se repite para tener como referencia.
En la configuración predeterminada de pantallas BP, establecemos un contexto de asignación de entrada opcional. Esto se aplica al activar o desactivar el widget, y puedes anularlo según cada clase.
UParrotActivatableScreen cuenta con una implementación para controlar las acciones de retroceso. El oyente de evento IA_UI_GenericBack se define en el gráfico de eventos de los blueprints derivados que lo utilicen. También necesitas habilitar la casilla Es controlador de regreso en el panel de detalles.
Consulta los comentarios de la clase C++ y BP para ver cómo se usa el patrón de regreso en diferentes widgets de pantalla.
Una vez cubiertas las clases base, echemos un vistazo a la pantalla de asignación de teclas. WBP_KeyBindingsScreen se encuentra en Content/UI/Widgets/Screens. Es buena idea que revises tu gráfico de eventos para ver cómo se consultan Ajustes de usuario y Perfil de teclas para obtener los tipos de Asignación de teclas del jugador desde Enhanced Input. Los datos son usados para añadir y rellenar widgets WBP_InputSelectorBox. Dentro del widget WBP_InputSelectorBox encontrarás dos widgets W_ParrotInputSelector.
Uno se usa para entradas de control y uno para entradas de teclado. El Selector de entrada 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 actualizan la pantalla.
Para mouse y teclado, trabajamos con el texto devuelto por el sistema de Enhanced Input y actualizamos la pantalla.
La implementación de un control depende de Common UI para consultar las imágenes específicas del control. En este caso, configuramos uno para imágenes de Xbox llamado
CommonInput_Gamepad_XboxenContent/Input/UI/Platform. Esta clase deriva deUCommonInputBaseControllerData.
A partir de esta clase, puedes asignar teclas de entrada de mapa a pinceles con imágenes. A continuación, configura los datos del control en Editar > Ajustes del proyecto > Ajustes de entrada común y navega hasta la plataforma.
Con esos datos conectados, el resto del trabajo se hace en los widgets. Vale la pena consultar el código y los comentarios enUParrotInputSelector y WBP_InputSelectorBox para ver exactamente cómo funciona la reasignación utilizando los subsistemas Enhanced Input y Common UI.
La última funcionalidad importante para destacar es cómo se guardan las teclas asignadas. Esto se hace en SaveKeyMappings en WBP_KeyBindingsScreen. Esta función itera por todos los widgets de cuadro selector y usa las funciones integradas Aplicar ajustes y Guardar ajustes de los ajustes del usuario. Guardar Ajustes escribe en el disco un archivo de guardado de juego, EnhancedInputUserSettings.sav. Se ubica en Directorio del proyecto > Parrot > Saved-SaveGames.
Si todo se configuró correctamente, ¡deberías tener una pantalla de asignación de teclas que funciona!
Notarás que en la esquina inferior derecha hay un widget de acción que se actualiza cuando la tecla es reasignada. Este 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 íconos específicos de la plataforma en función de una acción de entrada que utiliza los datos de entrada comunes que creamos anteriormente. Con Common UI es fácil crear tantos nuevos widgets como sean necesarios que hagan referencia a las acciones de Enhanced Input de tu juego.