Edu Segovia - ARTES

Videojuegos - Diseño - Sonido

Tutorial UE5 – Punto de mira detector

Crear en el HUD un punto de mira que cambia en función del tipo de objetivo que detecta.

Regreso a Posts
Videogames

(Esta es una función que una amiga quería hacer, y que yo me propuse probar a desarrollar a mi manera en Unreal Engine 5.1, agregando algunas otras características. Al final del tutorial se comparten los archivos de proyecto)


La idea

– Crear en el HUD un punto de mira que cambia en función del tipo de objetivo que detecta.

Qué se puede apreciar en el video:

  • El punto de mira sólo aparece cuando se pulsa el botón de apuntar (RMB) (la consola muestra texto en negro)
  • El punto de mira cambia a una más pequeña y roja con ciertos objetos (la consola muestra texto en rojo)
  • El punto de mira desaparece automáticamente a los 5 segundos (la consola no muestra nada)

Funcionalidad

Este sistema puede ser útil como detector de algún tipo de Actor con las propiedades que se deseen:

  • tecnología dentro del juego que detecta movimiento, temperatura, emisión de ondas…
  • reconocimiento de objetivos o NPCs con ciertas cualidades (inocentes, rehenes, enemigos, jefes o camuflados de incógnito…).

Se puede ampliar la funcionalidad agregando historia y programación de otros comportamientos a esta interacción (como texto, audio, cinemáticas, checkpoints, entre otros), utilizando el punto de mira como Trigger. Por ejemplo, es necesario volver a pulsar el botón para apuntar de nuevo. Según se aplique en la historia y la jugabilidad, puede no ser tan extraño “tomar un respiro al apuntar” cada 5 segundos.

De este modo, se puede ayudar al jugador a ubicarse dentro de la jugabilidad en una escena, o como recurso general del juego, si el personaje posee alguna virtud o herramienta especial.


Cómo lo he hecho

(Seguramente hay muchas versiones de esta funcionalidad, mejor diseñadas y con mejores prácticas de aplicación que la mía. Sin duda. Pero aquí está mi método)

  • El personaje utiliza la función LinetraceByChannel para reconocer el Tag de los actores con los que intersecta el “rayo”.
  • El jugador lanza esta función mediante un Input para evitar la sobrecarga del Tick (se desactiva automáticamente a los 5 segundos).

Blueprints que deben editarse o crearse (HUD), e imágenes que deben agregarse al proyecto:

En este gráfico se puede entender qué elementos son necesarios y la relación entre ellos.

El personaje:

Necesitas agregar 5 variables, 2 Eventos y 2 Funciones.

Las 5 variables:

  • isArmed (BOOLEAN): TRUE cuando se agarra el arma. Sirve para evitar que aparezca el punto de mira antes de ese momento, por lo que será el arma quien establezca esta variable.
  • isAiming (BOOLEAN): TRUE cuando el jugador acciona la función de apuntar mediante el INPUT (RMB). Recordemos que cambia automáticamente a FALSE a los 5 segundos.
  • isMortal (BOOLEAN): TRUE cuando el LinetraceByChannel interesecta con un objeto que posee la propiedad deseada. En este caso, el Tag “mortal”.
  • distanceMultiplier (INTEGER): VALOR ENTERO que sirve para multiplicar la distancia que el LinetraceByChannel alcanza para intersectar objetos. Mi configuración es 2000.
  • ref_HUD (OBJECT REFERENCE): Referencia al blueprint HUD creado. No es necesario crear esta variable, pero hace más fácil y limpia la llamada al HUD. Puedes “promover a variable” al crear HUD en el BeginPlay del personaje.

Los Eventos y las Funciones:

  • Aim: Detecta los objetos con el punto de mira. Ejecuta en secuencia las funciones AimLineTrace (LinetraceByChannel) y DetectMortality (ActorHasTag). Es lanzado desde el Tick tras 2 variables de control (isArmed y isAiming).
  • Crosshair swap: Intercambia ambos puntos de mira, o ninguno, mostrando/ocultando imágenes en el HUD, usando 3 variables de control. También es lanzado en el Tick.

El HUD:

Necesitas agregar 2 imágenes (.PNG con transparencia) en un lienzo.

Las 2 imágenes:

  • Punto de mira negro (grande): Aparece con el Input (RMB) del jugador y sirve para encuadrar cualquier objetivo.
  • Punto de mira rojo (pequeño): Aparece cuando LinetraceByChannel detecta un Actor con un Tag especificado en el código (“mortal“).

Ambas imágenes comparten las siguientes características en el panel Detalles:

  • Posición: (0,0) / Alineación (0.5,0.5). Con esta configuración estarán en el centro de la pantalla.
  • Comportamiento>Visibilidad: Colapsado. Con esta configuración no serán visibles por defecto.
  • Apariencia>Pincel>Tinta: Cada uno su color. De este modo se evitan algunos defectos del raster.
  • Variable. Asegúrate de que la casilla Is Variable (arriba a la derecha) está marcada.

Los objetos detectables:

Necesitas agregar un Tag a cada objeto que hará cambiar el punto de mira negro (grande) por el rojo (pequeño).

  • Las etiquetas (Tag) se agregan en el panel Componentes del objeto, en el panel Detalles, cuando se selecciona el objeto. Como se aprecia en la imagen, se pueden agregar varios Tag a cada objeto, lo que permite diversos funcionamientos, según el Tag que se utilice en la programación.
  • También hay que puntualizar que existen Tag de Actor y Tag de Componente, según en qué nivel del panel Componentes se configure el Tag. Esta configuración condiciona directamente a la función que se utilizará desde el personaje para comprobar el Tag del objeto interceptado mediante LinetraceByChannel (se verá después).

Una pequeña configuración:

Necesitas setear la variable isArmed en TRUE.

  • Recuerda que esta variable fue creada en el personaje, pero se seteará desde el blueprint del arma cuando ésta sea tomada por el jugador.
  • Para hacer esto, se obtendrá y cambiará la variable desde la referencia al jugador que se creará cuando ocurra la interacción entre el jugador y el arma (OnComponentBeginOverlap).

Enchufa y Juega:

Aquí va un vistazo general del blueprint del personaje, en donde todo sucede. (Disculpen por los textos en castellano)

Comencemos por la creación del widget HUD en el BeginPlay, y la creación de un CustomEvent que llamamos Crosshair swap:

  • Sí, al crear el widget, elegimos de la lista desplegable el HUD blueprint que hemos creado anteriormente.
  • Promovemos el valor retornado a variable de tipo Actor y le asignamos un nombre amigable. Ésta es la referencia al blueprint widget llamado HUD.
  • Programamos el cambio de visibilidad de las imágenes del HUD, según el caso que interese, utilizando las condiciones isArmed, isAiming, isMortal y la referencia al HUD recién creada.

¡Bien, ya casi el final! Ahora prosigamos con la creación del Input y del otro CustomEvent, llamado Aim, que concatena 2 funciones (AimLineTrace y DetectMortality) que también crearemos:

  • El Input es una tarea sencilla. Alterna el valor de la variable booleana de control isAiming al pulsar o soltar el botón derecho del ratón (RMB).
  • En la función AimLineTrace presta especial atención al OutHit del LinetraceByChannel. De ahí obtendremos las referencias de los items interceptados que utilizaremos para:
    • Comprobar que el objeto de intersecado es válido
    • Enviar las referencias de Actor o Componente intersecado a la posterior función DetectMortality.
  • Debes crear 2 Output en el retorno de la función para enviar las referencias obtenidas a la función de DetectMortality.
  • Sí, ahí está la variable distanceMultiplier para controlar la distancia del rayo del LinetraceByChannel.
  • En la función DetectMortality debes crear 2 Input en el inicio de la función para recibir las referencias al Actor o Componente intersecado desde la función AimLineTrace.
  • Estas referencias son utilizadas para establecer una condición comparativa de nombres mediante las funciones ActorHasTag o ComponentHasTag.
  • Del resultado verdadero de esta comparación se establecerá la variable isMortal en TRUE, indispensable para cambiar al punto de mira rojo (pequeño). Además, lo imprimiremos en consola para chequear.
  • Recuerda: en la comparación, los nombres deben mantener coincidencia de caracteres absoluta para que la condición se cumpla, así que recuerda bien el Tag que le adjudicaste al principio al item que quieres reconocer.
  • Se presentan otras opciones para casos en que el item interceptado disponga de más de un Tag y deba seleccionarse el deseado indicando el índice del Array en el que se almacenan tales valores Tag. Recuerda: Índice 0 = primer valor del Array, 1 = segundo, etc…

Por último, revisemos cuándo y cómo se activa el código agregado en el Tick del personaje:

  • Por defecto, se ejecutará el evento Crosshair swap no mostrando ningún punto de mira. (Puedes comprobar el flujo del código en curso activando la función DEBUG del blueprint, arriba a la derecha, cuando presiones el botón PLAY).
  • Cuando se posea el arma (isArmed) y se esté apuntando (isAiming) con el input RMB, se ejecutará el evento Aim (con las funciones LinetraceByChannel y DetectMortality). Se mostrará el punto de mira negro (grande) e imprimirá en consola “AIMING”, y cambiará al rojo (pequeño) imprimiendo en consola “MORTAL” cuando intercepte algún item con Tag “mortal”.
  • A los 5 segundos, isAiming se establecerá en FALSE, y se reseteará el Tick al estado inicial, teniendo que activar de nuevo el Input de jugador (RMB) para iniciar otra vez.

Información final

Revisión pendiente: El Tick

Se puede frenar el Tick en un momento temprano de comprobación de una variable booleana para que no esté seteando en cada frame la visibilidad de las imágenes del HUD. Probablemente se puede conseguir dividiendo la comprobación en 2 etapas y agregando una nueva variable booleana. Actualizaré esta cuestión.

Los archivos del projecto completo

Puedes descargar los archivos del projecto, creados en Unreal Engine 5.1.0. También adjunto los documentos de diseño.

Por favor, acredita mi trabajo si vas a utilizarlo en alguna ocasión y comunícamelo para estar en conocimiento.

Créditos

  • Unreal Engine 5.1.0
  • Adobe Illustrator
  • yEd
  • Young Frankenstein (Mel Brooks, 1974)

Aportes y Comentarios

Cualquier aporte al contenido, ya sea el método, la presentación o simplemente opiniones, será muy bien recibido, así que no dudes en utilizar la caja de comentarios. Tal vez podamos iniciar una conversación sobre el tema.

Leave a Reply

Your email address will not be published. Required fields are marked *