En esta parte del tutorial, crearás un PNJ enemigo que detectará, perseguirá y dañará al jugador. Además, el enemigo podrá recibir daño y recorrer el entorno para evitar obstáculos usando una malla de navegación.
Primero, crearás la lógica del enemigo usando secuenciación de comandos visual de Blueprint, como ya hemos hecho en los tutoriales anteriores. Luego, crearás la malla de navegación para definir las zonas por las que los personajes controlados por el controlador de IA pueden desplazarse durante la partida.
Antes de empezar
Asegúrate de que entiendes los temas tratados en la sección anterior El diseño de una aventura de puzles:
Blueprints y funciones de blueprint
Necesitarás los siguientes recursos de Cómo crear una llave:
Biblioteca de funciones de Blueprint
BPL_FPGame
Cómo crear una malla de navegación para el recorrido del enemigo
Antes de poder añadir al enemigo a un nivel y hacer que persiga al jugador, primero tienes que compilar la malla de navegación que usará la IA del enemigo para navegar por el nivel.
NavMesh es la abreviatura de Navigation Mesh (malla de navegación) y define áreas en el nivel dentro de las cuales la IA puede navegar. Al crear una malla de navegación en este tutorial, definirás una zona en la que el enemigo puede moverse para perseguir al jugador.
Para añadir una malla de navegación a tu nivel, sigue estos pasos:
En la barra de herramientas principal del editor de niveles de Unreal Editor, haz clic en el botón Crear, dirígete a Volúmenes y selecciona Volumen de límites de la malla de navegación. Esto crea una zona navegable para la IA en tu proyecto.
Con las herramientas de transformación, mueve la malla de navegación para que interseque con el suelo en tu nivel.
Pulsa la tecla P para activar o desactivar la vista de depuración. Utiliza esto para ver los detalles de la NavMesh en el visor de niveles, incluidas las zonas navegables del nivel, así como la información de depuración basada en texto en la parte izquierda del visor.
Si ves un mensaje «Hay que recompilar la malla del navegador» en la información de depuración, ve a Compilar > Compilar rutas en la barra de menús. Esto reconstruye tu malla de navegación.
Puedes seguir moviendo y escalando (teclas W y R) la malla de navegación para modificar sus límites. Escala este volumen como quieras.
Asegúrate de que la parte inferior de la malla de navegación sea lo suficientemente baja como para incluir cualquier pieza empotrada en el suelo y que la parte superior sea lo suficientemente alta para adaptarse a la altura del enemigo.
Si estás usando el nivel de muestra del tutorial, crea y escala dos volúmenes de límites de malla de navegación para que llenen el pasillo 3 y la sala 3.
A medida que escales y muevas la malla de navegación, verás que las zonas verdes se amplían con el tamaño del cuadro delimitador, a menos que tengas algunos objetos, como cubos. Cualquier parte que aparezca recortada en rojo indica que no son es navegable por la IA en tu juego.
Si Unreal Editor incluye algo en la malla de navegación que no debería, selecciona ese objeto de nivel de malla y desactiva Siempre puede afectar a la navegación en el panel Detalles.
Crea un enemigo
Crearás al enemigo a partir de la clase Personaje, puesto que ya incluye funciones de movimiento y animación que tienen sentido para un oponente humanoide. La clase Personaje en realidad es una extensión de Peón, que es el «actor controlable» más general usado para vehículos, cámaras o criaturas no humanoides. Para enemigos con forma de persona, Personaje es el mejor punto de partida.
Dado que estás creando este personaje desde cero, añadirás una malla para representar visualmente al enemigo y reproducirás una animación usando un blueprint de animación. El blueprint de animación se incluye en los archivos del proyecto, por lo que no tendrás que crearlo desde cero, pero es importante que aprendas a integrar uno con el blueprint del personaje enemigo.
Primero, crea el blueprint del enemigo. Sigue estos pasos:
En el explorador de contenido, ve a Contenido > AdventureGame > Diseñador > Blueprints > Personajes.
Haz clic con el botón derecho del ratón en cualquier lugar vacío del explorador de contenido y luego haz clic en Clase de blueprint.
En la nueva ventana, selecciona Personaje como clase base.
Dale a esta clase el nombre
BP_Enemyy ábrela en el editor de blueprints haciendo doble clic sobre ella.
Cuando creas una clase de Blueprint, eliges una clase padre a partir de la cual construir. Ese padre ya cuenta con funciones integradas. Por ejemplo, cuando creas blueprints a partir de la clase Actor, empiezas con una transformación y la capacidad de contener componentes y ejecutar lógica. Ahora, al empezar por la clase Personaje, también dispondrás de compatibilidad con el movimiento, las colisiones y las animaciones. La clase base se usa de forma similar a una plantilla. Cuando añades funciones, estás ampliando esa clase base.
Con la ventana del blueprint BP_Enemy abierta, ve a la pestaña Visor y observa el panel Componentes. Verás un componente de movimiento del personaje (CharMoveComp) al final de la lista. Todas las clases Personaje vienen con un componente de movimiento del personaje. Haz clic en el componente y observa el panel Detalles para ver todos los ajustes que contiene. Anularás algunos de estos ajustes a medida que vayas creando los enemigos en tu proyecto.
Cómo añadir un modelo 3D al enemigo
Tu personaje también viene con un componente de malla, pero en lugar de una malla estática, este componente es una malla esquelética. Las mallas estáticas con las que has trabajado hasta ahora son modelos 3D fijos que no se mueven, mientras que las mallas esqueléticas tienen un esqueleto interno que puede animarse y deformarse.
Primero, configura la malla y las animaciones del personaje. Sigue estos pasos:
Selecciona el componente de malla y observa en el panel Detalles . Busca la categoría Malla y haz clic en el desplegable que hay junto a Recurso de malla esquelética. En la lista, busca el modelo
SKM_Manny_Simpley selecciónalo. Esto asigna el modelo Manny al blueprint.En el panel Detalles, ve a la categoría Animación. Haz clic en el desplegable que hay junto a la clase Anim y asigna el blueprint de animación
ABP_Unarmed. Ahora, el personaje enemigo debería estar reproduciendo una animación inactiva en la pestaña Visor.Modifica el blueprint de animación para que funcione correctamente con nuestro enemigo:
En la propiedad de la clase Anim de la malla del enemigo, haz clic en Ir al recurso in explorador de contenido, junto a
ABP_Unarmed.Haz doble clic en el blueprint de animación
ABP_Unarmedpara abrirlo.Ve al grupo de lógica que hay después del pin Then 1 del nodo Sequence.
No quieres que la comprobación de la aceleración impida que los personajes enemigos se muevan, así que elimina la conexión entre el nodo And y el nodo Set Should Move.
Conecta el pin de salida del nodo Greater (>) al pin Should moverse, omitiendo la comprobación de aceleración.
Compila, guarda y cierra el blueprint.
En el visor, puedes ver una forma de cápsula cilíndrica alrededor del personaje enemigo. Esta es una representación visual del componente de cápsula que detecta colisiones con otros objetos, incluido el suelo. La malla del personaje tiene una forma más compleja, por lo que el cilindro de colisión simplifica la forma para mejorar el rendimiento de la detección de colisiones.
La malla está desfasada y no alineada con la cápsula. Para que la malla del personaje se alinee con el componente de cápsula, mueve el personaje hacia abajo para que los pies toquen la parte inferior del componente de cápsula.
Para alinear la malla del personaje con su volumen de colisión, sigue estos pasos:
Selecciona de nuevo el componente de malla para resaltar el modelo 3D.
En el panel Detalles, usa el campo Posición de la categoría Transformar para cambiar el eje Z, que es el último campo de color azul. Establece el valor en
-96.
Ahora ambos componentes están centrados en el origen para que el enemigo no flote por encima del suelo en el juego.
Por último, verás que el personaje tiene un componente Flecha (Arrow). La flecha indica la dirección frontal del blueprint. Asegúrate de que la flecha esté alineada con la dirección a la que apunta la malla para que el personaje corra en la dirección correcta.
Para que la malla del personaje mire hacia delante, sigue estos pasos:
Selecciona de nuevo el componente de malla. Usa el gizmo de rotación o la categoría Transformar del panel Detalles para rotar el personaje 90° en el eje Z. Su último valor de rotación debería ser -90.
Cómo cambiar el material del modelo 3D
Antes de pasar a la creación de funciones, cambia el color del modelo enemigo para que sea rojo. Eso lo distingue del jugador y hace que parezca más un enemigo, en lugar del color blanco actual.
Para cambiar el color del personaje enemigo, sigue estos pasos:
En la sección Materiales del panel Detalles, puedes ver que hay dos elementos:
MI_Manny_01_Newes el material que afecta a varias partes del modelo enemigo, como los brazos, las piernas y la cabeza.MI_Manny_02_Newes el material que afecta a los antebrazos y al torso.
Junto al Elemento 0, haz clic en el botón Buscar en el explorador de contenido (icono de una carpeta y una lupa). Esto abre la carpeta que contiene este material en el explorador de contenido. El segundo material,
MI_Manny_02_New, también está aquí.Haz clic derecho en el recurso
MI_Manny_01_Newy luego haz clic en Crear instancia de material.Dale a la instancia de material el nombre
MI_Enemy_01y haz doble clic para abrirla.En el panel Detalles, amplía 01 - BaseColor y activa la propiedad Tono de pintura.
Haz clic en la muestra de color que hay junto a la propiedad Tono de pintura y selecciona un color. En este tutorial usamos sRGB hexadecimal =
F60E6EFF.Haz clic en Guardar y cierra la ventana.
De nuevo en el explorador de contenido, haz clic derecho en
MI_Manny_02_Newy haz clic en Crear instancia de material.Dale a esta instancia de material el nombre
MI_Enemy_02y repite los pasos anteriores para cambiar el color y guardar el recurso.
Una vez repetidos los pasos, deberías tener dos nuevas instancias de material: MI_Enemy_01 y MI_Enemy_02.
A continuación, para asignar estos materiales al personaje enemigo, haz lo siguiente:
En el blueprint
BP_Enemy, en el panel Detalles, ve a la sección Materiales.Haz clic en el desplegable Elemento 0 y selecciona el nuevo material que has creado (
MI_Enemy_01).EnElemento 1, cámbialo al material
MI_Enemy_02.
Cómo añadir un enemigo al nivel
Añade un enemigo a tu nivel para ver qué aspecto tiene y cómo se comporta hasta el momento.
Desde el explorador de contenido, arrastra el blueprint del enemigo al visor de nivel y colócalo delante del jugador.
Cuando juegues, deberías ver al enemigo animarse con una animación de reposo.
Configura el enemigo cuando empiece la partida
Con el enemigo listo desde una perspectiva visual, puedes crear las funciones de jugabilidad. Primero configurarás las propiedades necesarias del enemigo cuando aparezca.
Para definir la velocidad de movimiento del enemigo cuando comience la partida, sigue estos pasos:
En la ventana del editor de blueprints
BP_Enemy, ve a la pestaña EventGraph. De forma predeterminada, hay tres eventos: Event BeginPlay, Event ActorBeginOverlap y Event Tick. Selecciona ActorBeginOverlap y bórralo, ya que no es necesario para este tutorial.Usando el panel Componentes, arrastra el componente Movimiento del personaje al grafo de eventos. Esto crea un nodo Character Movement. Con este nodo del componente, puedes comprobar o cambiar las propiedades de ese componente desde el grafo.
Arrastra el pin del nodo Character Movement y crea un nodo Set Max Walk Speed.
Haz clic derecho en el pin verde Max Walk Speed del nodo Set y selecciona la opción Promocionar a variable.
Como resultado, se creará una nueva variable en el panel My Blueprint bajo la lista Variables.
Cambia el nombre de la variable a
Velocidad máxima. Haz clic en el icono del ojo que hay junto a la variable para convertirla en una variable pública y editable.Cambia su categoría a Configuración.
Compila el blueprint y, en el panel Detalles, establece el valor predeterminado de Velocidad máxima en
200.Asigna siempre un valor predeterminado a tus variables editables. Si olvidaste cambiar su valor en el editor de niveles, y el valor predeterminado era 0, el enemigo no podría moverse.
Conecta Event BeginPlay al nodo Set Max Walk Speed.
A continuación, dos variables rastrearán la salud del enemigo. TotalHP, una variable editable en la instancia, establece los puntos de salud iniciales del enemigo. CurrentHP registra cuánta salud tiene el enemigo durante la partida, ya que recibe daño del jugador o del entorno.
Para establecer los puntos salud (PS) del enemigo, sigue estos pasos:
En la lista Variables, añade una nueva variable nombrada
CurrentHPde tipo float.Arrastra la variable CurrentHP desde la lista Variables al grafo de eventos y selecciona la opción Set Current HP. Arrastra el pin de ejecución del nodo Set Max Speed y conéctalo al pin de ejecución del nodo Set Current HP.
En el nodo Set Current HP, haz clic derecho en el pin float Current HP y haz clic en Promocionar a variable.
Cambia el nombre de esta variable a TotalHP. Asegúrate de que su tipo sea float y haz clic en su icono de ojo para que sea público y editable. En el panel Detalles, establece Categoría en Configuración. Compila el blueprint y establece el valor predeterminado en
100.Conecta los pines de ejecución entre los nodos Set.
En este grafo de eventos, vas a realizar muchas acciones con el personaje jugable, así que lo siguiente es guardar una referencia al jugador como variable.
Para configurar una variable para el personaje jugable, sigue estos pasos:
En la lista Variables, crea una nueva variable llamada
PlayerRefy cámbiale el tipo a Personaje (referencia a objeto).Crear una variable de referencia para el objeto del personaje es mejor para el rendimiento de tu proyecto que llamar a la función Get Player Character cada vez que necesites referenciar al jugador.
Después del nodo Set Current HP, conecta un nodo Set PlayerRef.
Para su pin de entrada Player Reference, conecta un nodo Get Player Character. Asegúrate de que el valor de Índice del jugador sea 0. Este es el índice predeterminado para el primer personaje jugable que aparece en el nivel.
Haz que el enemigo persiga al jugador
A continuación, crearás la lógica para mover al enemigo hacia el jugador. Puedes hacerlo creando un evento personalizado. Llama a eventos personalizados desde cualquier parte del blueprint para activar y ejecutar lógica.
Para crear un evento personalizado que desencadene una acción de movimiento, sigue estos pasos:
Haz clic derecho en cualquier parte del grafo de eventos y escribe
Evento personalizadoen el campo de búsqueda. Haz clic en la opción Añadir evento personalizado de la lista y dale a este evento el nombre MoveToPlayer.Arrastra el pin del nodo del evento MoveToPlayer y crea un nodo IA MoveTo. Este nodo es una acción que los peones con AIController usan para moverse a una ubicación específica. En este caso, lo usarás para mover al enemigo hacia el jugador.
En el nodo IA MoveTo, arrastra el pin Pawn y escribe
Sí mismoen el campo de búsqueda. Selecciona Obtener una referencia a sí mismo para crear un nodo que haga referencia al actor de este blueprint en el juego.Arrastra el pin Target Actor del nodo IA MoveTo y crea un nodo Get PlayerRef.
Establece Radio de aceptación en
10. Es la distancia en centímetros a la que el enemigo considera que ha llegado a su destino. Te da más control que detenerte en superposición.
En este caso, estás usando el nodo Self para definir a este enemigo como el peón que debe moverse. A continuación, establece el jugador como actor objetivo (el objetivo hacia el que se moverá el peón).
El nodo IA MoveTo incluye eventos Al tener éxito y Al fallar. Estos definen qué sucede si el enemigo alcanza al jugador o si falla.
Para definir qué ocurre después de que el enemigo se mueva, sigue estos pasos:
En el nodo IA MoveTo, arrastra el pin On Success y crea un nodo Delay.
Haz clic derecho en el pin Duration del nodo Delay y selecciona Promocionar a variable.
Nombra esta variable WaitAtDestination y asegúrate de que su tipo sea float.
Compila el blueprint y cambia el valor predeterminado de WaitAtDestinationa
5. Haz clic en el icono de su ojo para poder editarlo y cambia su categoría a Configuración.En el grafo de eventos, arrastra el pin de ejecución del nodo Delay y crea un nodo Move To Player. Esto garantiza que el enemigo siga persiguiendo al jugador si se aleja, pero después de un retraso que le da al jugador la oportunidad de ganar algo de distancia.
Desde el nodo IA MoveTo, arrastra el pin On Fail y crea un nuevo nodo Delay.
Arrastra el pin Completed del nodo Delay y crea un nodo Move To Player. Deja la duración en 0.2. Esto asegura que el enemigo siga moviéndose si aún no ha alcanzado al jugador.
En el grupo de lógica Event BeginPlay al final de esta secuencia, después del nodo Set Player Ref, conecta un nodo Move To Player para activar este evento. Esto hace que el enemigo se mueva al principio de la partida y que puedas probar así su movimiento.
Guarda y compila el blueprint.
Ahora tu grafo de eventos debería tener este aspecto:
Cómo probar el movimiento del enemigo
En tu nivel, mueve tu actor enemigo para que esté dentro de los límites de la malla de navegación, es decir, en las zonas verdes.
Selecciona el actor BP_Enemy en el visor de niveles o en el esquematizador. En el panel Detalles, verás las variables que has añadido al blueprint en la sección Configuración. Puedes cambiar estos valores para adaptarlos a las necesidades de tu proyecto o activar Detección de depuración para permitir el dibujado de depuración del trazado de línea.
Vuelve a jugar tu nivel para ver cómo se comporta ahora el enemigo. Debería caminar hacia el jugador, detenerse cuando lo alcance, esperar 5 segundos y volver a intentar caminar hacia el jugador.
Si algo no funciona como debería, comprueba si las variables que has creado en el blueprint tienen los valores correctos establecidos en el BP_Enemy en la escena. Si no fijas los valores de Velocidad máxima o Distancia máxima de detección, el enemigo no se moverá. Lo mismo podría ocurrir si los valores son demasiado bajos.
Cómo infligir daño al jugador
Ahora que el enemigo puede alcanzar al jugador, puedes añadir funciones que hagan que el enemigo dañe al jugador cuando colisionen. En este tutorial, vas a crear un enemigo que se autodestruirá al entrar en contacto con el jugador, por lo que también añadirás lógica para eliminar a ese enemigo después de que haya infligido daño al jugador una vez.
Para comprobar si el enemigo ha chocado con el jugador, sigue estos pasos:
En el panel Componentes , haz clic derecho en el componente de cápsula (CollisionCylinder), ve a Añadir evento y selecciona Añadir OnComponentHit.
Esto crea un nuevo nodo de evento en el grafo de eventos que se ejecuta cuando el componente de cápsula impacta contra algo.
Arrastra el pin del nodo On Component Hit y crea un nodo Branch.
Conecta el pin Condition con el pin Other actor del nodo On Component Hit. Al hacerlo, se te pedirá que crees un nuevo nodo.
Crea un nodo Equal. Arrastra el pin Seleccionar recurso del nodo Equal y añade una referencia a la variable PlayerRef.
Ahora, esta lógica activa un evento cuando el componente de cápsula del enemigo golpee contra algo en el juego. El evento comprueba si el componente de cápsula ha impactado al personaje jugable.
Para infligir un golpe de daño al jugador y eliminar al enemigo, sigue estos pasos:
En la lista Variables, crea una nueva variable nombrada Eliminated y cámbiale el tipo a booleano. La usarás cuando el enemigo sea derrotado y deba eliminarse del juego.
Para garantizar de que solo se daña al jugador una vez, arrastra el pin True del nodo Branch y crea un nodo Do Once.
Desde el pin Completed del nodo Do Once, crea un nodo Apply Damage. Arrastra el pin Damaged Actor y conecta una referencia a la variable PlayerRef. Este es el actor que debería recibir el daño.
Haz clic derecho en el pin Base Damage y selecciona Promocionar a variable.
En la lista Variables, haz clic en el icono de ojo de Daño basepara poder editarlo y cambia su categoría a Configuración. Compila el blueprint y establece el valor predeterminado en
25.Arrastra la variable Eliminated desde la lista Variables hasta el grafo de eventos y selecciona el nodo Set. En el nodo, haz clic en la casilla de verificación para activar Eliminated.
Conecta el pin de ejecución del nodo Apply Damage con el nodo Set Eliminated.
Arrastra el pin de ejecución del nodo Set Eliminated y crea un nodo Delay. Ajusta la duración en
2.0.Arrastra el pin de ejecución del nodo Delay y crea un nodo Destroy Actor. La propiedad Objetivo debe establecerse como Sí mismo de forma predeterminada.
Cuando el enemigo colisiona con el jugador, inflige daño al jugador y mata al enemigo después de un retraso de 2 segundos.
Ahora, el enemigo puede correr hacia el jugador, infligir daño y autodestruirse cuando colisiona con el jugador. Sin embargo, no tiene en cuenta la distancia ni los obstáculos entre el jugador y el enemigo. Así que el enemigo siempre persigue al jugador sin importar la distancia o la línea de visión.
La lógica terminada de BP_Enemy para On Component Hit debería parecerse a lo siguiente:
Para copiar el fragmento del blueprint de abajo en tu grafo de eventos BP_Enemy, asegúrate de que los nombres de las variables coincidan con los del proyecto de muestra.
Añade lógica de obstáculos y distancia
A continuación, añade una distancia máxima de detección para que el enemigo solo pueda detectar al jugador cuando esté lo suficientemente cerca. Luego, termina implementando restricciones en la línea de visión del enemigo para que no puedan ver al jugador a través de las paredes.
Para ello, primero tendrás que crear una nueva función en tu biblioteca de blueprints que trace una línea entre el enemigo y el jugador.
Calcula la línea de visión y la distancia con un trazado de línea
Un trazado de línea (o proyección de rayos) es una práctica habitual en el desarrollo de videojuegos. Los trazados de línea dibujan una línea invisible desde un punto del mundo (como un actor fuente) para ver con qué impacta. Suele usarse para detectar objetos o superficies en tiempo de ejecución y poder activar la lógica en función del resultado del trazado.
En este tutorial, realizarás un trazado de línea desde el personaje enemigo para detectar cuándo el personaje jugable está en la línea de visión del enemigo.
Para obtener más información sobre los trazados de línea, consulta Traces with Raycasts en la documentación.
Para configurar una función que use un trazado de línea para encontrar al jugador, sigue estos pasos:
En el explorador de contenido, ve a tu carpeta Core y abre la biblioteca de blueprints
BPL_FPGame.Añade una nueva función con el nombre
fnBPLFindPlayer.En el panel Detalles de la nueva función, en la sección Entradas, haz clic en Añadir (+) para añadir las siguientes entradas:
Referencia de jugador (referencia de objeto de peón)
Posición inicial (vector)
Distancia máxima de detección (float)
Depurar (booleano)
Después de añadir estas entradas, nodo de entrada fnBPLFindPlayer de la función tiene los pines correspondientes para cada una de las variables.
En el panel Detalles de la función, en la sección Salidas, haz clic en Añadir (+) para crear un valor de salida de tipo booleanollamado Found.
Tras añadir la salida de Found, aparece un nuevo nodo Return en el grafo con el pin Found.
En la sección Variables locales del panel My Blueprint, haz clic en Añadir (+) para crear una variable local llamada PlayerFound de tipo booleano. Asegúrate de que su valor predeterminado sea false.
La referencia del jugador es fundamental para que la función se ejecute correctamente, así que cuando se inicie la función, verifica si hay una referencia válida del jugador para evitar errores.
Para comprobar la entrada válida, sigue estos pasos:
Elimina la unión entre el nodo Entry y el nodo Return manteniendo pulsada la tecla Alt y haciendo clic en la unión o en cualquiera de los pines de ejecución.
Después del nodo de función de entrada, crea y conecta un nodo Is Valid.
Asegúrate de crear un nodo Is Valid representado con un icono de signo de interrogación (?) cerca de la parte inferior de la lista de acciones del nodo.
Conecta el pin Player Reference del nodo de entrada con el pin Input Object del nodo Is Valid.
Conecta el pin de ejecución No es válido al nodo Return.
Para el valor de retorno Found, conecta una referencia a la variable PlayerFound. Esto cierra la función y devuelve PlayerFound=False al grafo de eventos del enemigo.
Si el jugador es válido, la función debería ejecutar el objeto de trazado de línea y luego devolver PlayerFound.
Para configurar el trazado de línea, sigue estos pasos:
Desde el pin de ejecución Es válido, añade un nodo Sequence para organizar tu lógica.
Arrastra desde el pin Then 0 del nodo Sequence y añade un nodo Line Trace By Channel.
El nodo Line Trace By Channel detecta objetos en un canal de colisión específico. Para ver los ajustes del canal de colisión de un blueprint, selecciona el componente de colisión del blueprint y ve a las propiedades Colisión> Preajustes de colisión en el panel Detalles. La sección Respuestas de trazado tiene canales de visibilidad y de cámara.
Desde el nodo de entrada de la función, arrastra el pin Start Location y conéctalo al pin Start del nodo Line Trace By Channel. Esto define la posición del personaje enemigo como punto de partida para el trazado de línea.
Para mantener tu grafo ordenado, crea un nodo Get Player Reference. El icono f de la esquina superior derecha del nodo indica que se trata de una entrada de función. Puedes añadir referencias a estas entradas como lo harías con cualquier otra variable.
Arrastra desde el pin Player Reference hasta un punto en blanco del grafo. Esto abre la lista de acciones del nodo. En la lista, busca y crea un nodo Get Actor Location.
Conecta su valor de retorno al pin End del nodo Line Trace. Finaliza el trazado en la posición del jugador.
En el nodo Line Trace By Channel, establece la propiedad Canal de trazado como Cámara usando el menú desplegable.
Ahora que ya has definido dónde empieza y acaba el trazado de línea, define qué ocurre cuando el trazado toca algo.
Para comprobar si un trazado de línea ha impactado al jugador, sigue estos pasos:
Arrastra desde el pin Out Hit del trazado de línea y añade un nodo Break Hit Result. Cuando un trazado de línea impacta en un objeto, se recopila una gran cantidad de información. A los efectos de esta lógica, solo necesitamos usar unos pocos valores específicos, por lo que se necesita un nodo Break Hit Result para dividir los datos en los componentes individuales de los datos devueltos.
En el nodo Break Hit Result, haz clic en la flecha de la parte inferior para ver más opciones.
Quieres saber si el jugador está en la línea de visión y dentro de una cierta distancia del enemigo, por lo que usarás Impactar actor para buscar al jugador y usarás los nodos Trace Start y Trace End para medir la distancia al objeto golpeado.
Arrastra desde el pin Hit Actor y añade un nodo operador Equal. Para la entrada inferior, conecta una referencia a la entrada de la función Referencia del jugador.
Para hacer referencia a valores de entrada de función, puedes añadir un nodo Get similar a otras variables.
Crea un nodo Distance (Vector). Conecta V1 con Trace Start y conecta V2 con Trace End.
Un vector es un conjunto de valores X, Y y Z que representan la posición de un objeto o punto en el espacio 3D. El nodo Distance calcula la distancia entre dos de estos puntos, lo que da como resultado un valor float.
Arrastra desde el valor de retorno del nodo Distance y añade un nodo Less (<). Para la entrada inferior, conecta una referencia a la entrada de función Distancia máxima de detección.
Crea un nodo AND (Boolean).
Conecta los pines de salida booleanos de los nodos Equals (==) y Less (<) con los pines de entrada del nodo AND.
Con esta lógica, el nodo AND se activa si el trazado de línea golpea a un actor que sea igual a la referencia del jugador, y la distancia entre el inicio del trazado (el enemigo) y el final (el objeto golpeado) es menor que la distancia máxima de detección.
Si quieres usar el resultado del trazado para establecer y devolver el valor de PlayerFound, sigue estos pasos:
Arrastra desde la salida del nodo AND y añade un nodo Branch.
Conecta su pin de ejecución para que se ejecute después de Line Trace By Channel.
Desde el pin de ejecución True del nodo Branch, crea un nodo Set Variable para activar la variable local PlayerFound.
Desde el pin False del nodo Branch, crea un nodo Set Variable para desactivar la variable local PlayerFound. Mantén el valor desactivado (false).
Ya has terminado con la lógica del trazado de línea, así que vuelve al nodo Sequence y conecta Luego 1 al nodo Return para salir de la función y enviar el resultado de PlayerFound al blueprint de enemigo.
Cómo añadir una opción de depuración de trazado de línea
Quieres poder activar y desactivar fácilmente un elemento visual de depuración del trazado de línea desde el editor de niveles. Sin embargo, el nodo Line Trace solo te permite elegir una opción de la lista Tipo de depuración de trazado. Puedes usar un nodo Select para hacer que el tipo de depuración sea editable en el editor de niveles.
Para configurar una opción de depuración personalizable para el trazado de línea, sigue estos pasos:
Arrastra desde el pin Draw Debug Type del nodo Line Trace By Channel, crea un nodo Select.
Conecta el pin Index del nodo Select a una referencia a la entrada Debug de la función.
El índice del nodo Select es un comodín, por lo que cuando conectas el valor de tipo booleano Debug, las opciones cambian a False y True.
Establece la opción False como Ninguno. Activa la opción For Duration.
En la parte inferior del nodo Line Trace By Channel, haz clic en el botón de la flecha para ver más opciones. Cambia el tiempo de dibujo a
0.1segundos.Guarda y compila tu biblioteca de funciones Blueprint.
Esta lógica usa la variable Debug para determinar si el dibujado de depuración del trazado de línea está activo o no:
Cuando la variable Debug está desactivada, el tipo de dibujo de depuración se establece en None, lo que significa que no se renderiza ningún dibujo de depuración.
Cuando Debug se activa, el nodo Select cambia el tipo de dibujo de depuración a For Duration, que renderiza el trazo de línea en tiempo de ejecución durante un tiempo definido.
La función terminada fnBPLFindPlayer debería tener el siguiente aspecto:
Si copias este fragmento de blueprint en tu proyecto, tendrás que conectar el pin de ejecución y Player Reference del nodo de entrada de función al pin de ejecución e Input Object del nodo Is Valid. Para que el fragmento se copie correctamente, verifica que los nombres de las entradas de función coincidan con los del proyecto de muestra.
Lógica de actualización para el movimiento hacia el jugador
Ahora que puedes llamar a una función que busque al jugador teniendo en cuenta la distancia y la línea de visión, añadir lógica al enemigo que le obligue a buscar y perseguir al jugador en cuanto esté a tiro o cuando el trazado de línea encuentra correctamente al jugador.
Para hacer que el enemigo persiga al jugador después de encontrarlo, sigue estos pasos:
Vuelve al blueprint
BP_Enemy. En el grafo de eventos, busca el nodo Event Tick proporcionado.Arrastra el pin de ejecución del nodo Event Tick y crea un nodo Branch.
El evento On Tick se ejecuta en cada fotograma mientras se reproduce el juego. Úsalo para que el enemigo compruebe constantemente la posición del jugador y determine si debe iniciar la persecución.
Arrastra el pin Condition del nodo Branch y crea un nodo NOT Boolean que devuelva el valor inverso de un valor booleano.
En este caso, quieres negar la variable Eliminated, así que arrastra el pin de entrada del nodo NOT y busca Get Eliminated.
Esto comprueba si el enemigo no está eliminado antes de continuar con el Verdadero del nodo Branch.
Arrastra el pin True del nodo Branch y crea un nodo FnBPLFindPlayer. Este nodo realiza un trazado de línea para encontrar al jugador en el mundo y comprueba la distancia actual entre el enemigo y el jugador.
En el nodo Fn BPLFind Player, haz las siguientes conexiones usando sus pines:
Referencia del jugador: conecta una referencia a la variable PlayerRef.
Posición inicial: crea un nodo Get Actor Location con la propiedad Objetivo establecida en Sí mismo. Esto asigna la posición inicial del trazado de línea a la posición del enemigo en el mundo.
Distancia máxima de detección: haz clic derecho en el pin y selecciona Promocionar a variable. Haz clic en el icono de su ojo para poder editarlo y cambia su categoría a Configuración. Compila y fija su valor predeterminado en
20000(200 metros). Cuanto menor sea este valor, más cerca tendrá que estar el jugador para que los enemigos lo detecten.Depurar: selecciona Promocionar a variable y nómbrala
DebugDetection. Haz que esta variable también sea editable y que aparezca en la categoría Configuración.
Si el trazado de línea encuentra al jugador, establece la velocidad máxima de movimiento del enemigo en la cantidad deseada, moviendo al enemigo hacia el jugador. De lo contrario, deberías establecer la velocidad en 0 para que el enemigo no pueda moverse hacia el jugador.
Para hacer que el enemigo se mueva cuando se encuentra al jugador y se detenga cuando no se encuentra al jugador, sigue estos pasos:
En el nodo FnBPLFindPlayer, haz clic derecho en el pin Found y selecciona Promocionar a variable. Esto conecta automáticamente un nodo Set para esa nueva variable. Ahora puedes usar este resultado de Encontrado en cualquier parte del grafo.
Después del nodo Set, conecta un nodo Branch. Arrastra el pin Condition del nodo Branch hasta el pin de salida del nodo Set Found.
En el panel Componentes, arrastra el componente Movimiento del personaje (CharMoveComp) al grafo de eventos. Arrastra su pin y crea un nodo Set Max Walk Speed.
Arrastra el pin True del nodo Branch y conéctalo al nodo Set Max Walk Speed.
Para el pin Max Walk Speed del nodo Set, conecta una referencia a la variable Max Speed.
Después del nodo Set, conecta un nodo MoveToPlayer para llamar a ese evento y hacer que el enemigo se mueva solo si ha encontrado al jugador.
Duplica los nodos Set Max Walk Speed y Character Movement. Conecta el pin False del nodo Branch al nuevo nodo Set.
En el segundo nodo Set Max Walk Speed, garantiza que el valor de la velocidad a pie sea 0. Esto hace que el enemigo deje de moverse sin cancelar su tarea AI MoveTo y sin tener que ejecutar la tarea de nuevo.
Ahora que el enemigo está buscando al jugador en cada fotograma, elimina el nodo Move to Player que has añadido al final de la lógica de Event BeginPlay. Este nodo era útil para probar un enemigo parcialmente completado, pero ya no lo necesitas.
Ve a la lógica de tu evento MoveToPlayer. Ahora lo único que quieres es que el enemigo ejecute esto si el jugador ha sido encontrado:
Arrastra el pin del nodo MoveToPlayer y crea un nodo Branch.
En el pin Condition del nodo Branch, añade una referencia a la variable Found.
Ahora, si el jugador se encuentra dentro de la distancia indicada del enemigo y no hay obstáculos entre ambos, la velocidad de movimiento del enemigo se establecerá en la variable MaxSpeed y ejecutará la lógica MoveToPlayer. Si no se cumple ninguna de estas condiciones, la velocidad de movimiento del enemigo se establecerá en 0, lo que impedirá que el enemigo se acerque al jugador.
La lista final de variables de BP_Enemy debería tener el siguiente aspecto:
Para copiar los fragmentos del blueprint de abajo en tu grafo de eventos BP_Enemy, asegúrate de que los nombres de las variables coincidan con los del proyecto de muestra.
La lógica final de BP_Enemypara Event BeginPlay debería tener el siguiente aspecto:
La lógica final de BP_Enemypara MoveToPlayer debería tener el siguiente aspecto:
La lógica final de Event Tick para BP_Enemy debería tener el siguiente aspecto:
Permite que los enemigos reciban daño
Antes de acabar con este blueprint, tienes que asegurarte de que el enemigo también pueda recibir daño. Si sigues trabajando en tu juego más allá de esta serie de tutoriales, puede que te interese que las trampas dañen a los enemigos o que quieras darle al jugador un objeto equipable que pueda dañar y eliminar a los enemigos.
Para hacer que los enemigos reciban daño, sigue estos pasos:
Haz clic derecho en cualquier parte del grafo de eventos y crea un nodo Event AnyDamage.
Arrastra el pin de ejecución desde Event AnyDamage y crea un nodo Set CurrentHP.
Para sustraer el daño infligido de CurrentHP, arrastra el pin de la propiedad Current HP y crea un nodo Subtract.
Arrastra el pin superior del nodo Subtract y crea un nodo Get Current HP.
Conecta el pin inferior del nodo Subtract a la propiedad Damage del nodo Event AnyDamage.
Cuando se inflija cualquier daño a este actor, se tomará el valor de la variable CurrentHP, se le restará el daño y, a continuación, se establecerá el valor de CurrentHP en el nuevo valor.
Ahora comprueba si CurrentHP es menor o igual a 0, lo que debería eliminar al enemigo.
Para eliminar al enemigo cuando su PS sea 0, sigue estos pasos:
Arrastra el pin del nodo Set y crea un nuevo nodo Branch.
Arrastra el pin Condition del nodo Branch y crea un nodo Less Equal (<=).
Conecta el pin de salida del nodo Set Current HP al pin de entrada superior del nodo Less Equal. Asegúrate de que el pin inferior esté establecido en 0.
Arrastra el pin True del nodo Branch y crea un nodo Do Once.
Arrastra su pin Completed y crear un nodo Set Eliminated. En el nodo Set, activa la propiedad Eliminado.
Después del nodo Set,conecta un nodo Delay con la duración fijada en
2.Arrastra el pin Completed del nodo Delay y crea un nodo Destroy Actor con la propiedad Objetivo establecida en Sí mismo.
Guarda y compila el blueprint.
La lógica terminada de BP_Enemypara Event AnyDamage debería tener el siguiente aspecto:
Prueba del personaje enemigo finalizado
Si pruebas el juego ahora, dependiendo de la distancia entre el enemigo y el jugador, es posible que el enemigo no se esté moviendo. Si te acercas al enemigo, este debería empezar a perseguir al jugador.
Pruébalo con un obstáculo. Sal del modo de juego y añade un cubo o una pared de bloqueo en el centro de la zona de la malla de navegación pulsando el botón Crear en la barra de herramientas principal y seleccionando Formas > Cubo. Este obstáculo corta la malla de navegación.
Si el jugador comienza detrás de este obstáculo, el enemigo no puede perseguir al jugador, ya que el cubo bloqueará el trazado de línea, por lo que el enemigo no podrá encontrar al jugador. Si el jugador camina por el cubo y el enemigo lo ve directamente, empezará a seguir al jugador. Una vez que el enemigo inicia su acción IA MoveTo, esconderse detrás de un obstáculo no detendrá su persecución.
Si quieres que un enemigo vea al jugador a través de un obstáculo, selecciona el objeto de nivel y ve a Colisión > Preajustes de colisión en el panel Detalles. Cambia el preajuste a Personalizado y activa Ignorar en el canal Cámara. Para que un objeto bloquee el trazo de línea, vuelve a cambiar el preajuste a Predeterminado.
Cómo colocar las posiciones del enemigo en tu proyecto
En nuestro nivel de muestra, colocamos varios enemigos en el pasillo 3 y en la sala 3. El primer enemigo está solo en el pasillo 3 para ofrecer al jugador un primer encuentro sencillo y ayudarle a aprender el comportamiento y las habilidades del personaje enemigo. Después de encontrarnos con el único enemigo del pasillo, añadimos dos personajes enemigos más a la sala 3 para complicar más el desafío para el jugador.
Puedes variar la cantidad y los tipos de enemigos para proporcionar distintos niveles de dificultad a lo largo de tu proyecto. Al presentar a los jugadores nuevos enemigos y desafíos poco a poco, se crea una curva de dificultad equilibrada a la que el jugador puede acostumbrarse con el tiempo. Crear un encuentro enemigo difícil después de permitir que el jugador aprenda a navegar y derrotar a los enemigos, proporciona un desafío que puede resultar gratificante para el jugador.
Siguiente
En el siguiente módulo, aprenderás cómo añadir una mecánica de esprint al conjunto de movimientos del jugador. Esto ayuda al jugador a moverse por lugares familiares en el nivel y también le proporciona una herramienta para evitar a los enemigos que acabas de añadir al proyecto.