Los marcadores de objetivo se utilizan en muchos juegos para guiar al jugador hacia el siguiente objetivo o punto de interés. En este tutorial, aprenderás a hacer un marcador de objetivo reutilizable con el dispositivo Indicador del mapa y Verse.
Funciones del lenguaje Verse utilizadas
struct: puedes agrupar variables de diferente tipo en un struct.
Método de extensión: un tipo especial de función que actúa como miembro de una clase o tipo existente, pero que no requiere la creación de un nuevo tipo o subclase. En esta guía, crearás un método de extensión para struct.
Argumento con nombre: un argumento que se pasa a una llamada a función con su nombre de parámetro especificado.
API de Verse utilizadas
API creative_prop: la API
creative_propproporciona métodos para el movimiento de los elementos.Propiedades editables: se utilizan varias propiedades tanto para referenciar dispositivos como para actualizar valores variables para pruebas rápidas.
Instrucciones
Sigue estos pasos para aprender a configurar un dispositivo marcador de un solo objetivo que pueda desplazarse a varios objetivos o puntos de interés. Las secuencias de comandos completas se incluyen al final de esta guía como referencia.
Cómo configurar el nivel
Este ejemplo utiliza los siguientes elementos y dispositivos.
1 elemento de construcción: un elemento que se utilizará para mover el dispositivo Indicador del mapa.
1 dispositivo Indicador de mapa: un dispositivo que mostrará marcadores personalizados en el minimapa y en el mapa general.
1 dispositivo Plataforma de aparición de jugador: añádelo cerca del elemento para que el jugador aparezca cerca.
Utilización de la API de elementos
El primer paso para conseguir que un dispositivo se mueva con Verse es mover un elemento con la API de elementos. Sigue estos pasos para mover un elemento por tu nivel.
Crea un nuevo dispositivo de Verse nombrado objective_coordinator_device.
En las expresiones predeterminadas
usingde la parte superior del archivo Verse, añade una expresiónusingpara el módulo SpatialMath. Este módulo contiene código de referencia para mover elementos.Verseusing { /UnrealEngine.com/Temporary/SpatialMath }Añade dos propiedades editables:
Una constante
creative_propnombradaRootProppara almacenar una referencia al elemento móvil.Una constante
transformnombradaDestinationpara almacenar la ubicación a la que se moverá el elemento.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
Si ejecutas este código y arrastras tu objective_coordinator_device al nivel, verás las dos propiedades en el panel Detalles.
El método
TeleportTo[]es el que realmente mueve el elemento. Llámalo dentro de una expresión `if` y utiliza corchetes en lugar de paréntesis, ya queTeleportTo[]es una expresión falible. Elifcrea un contexto de fallo.Verseif(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Prop move successful") else: Print("Prop move failed")Los argumentos de
TeleportTo[]son Translation y Rotation. Ambos proceden de tu propiedad Destination.De vuelta en el editor, arrastra un elemento desde Fortnite > Galerías > Elementos en el explorador de contenido. El que se utiliza en esta guía se llama Coastal Buoy 02B, pero debería funcionar cualquiera de los incluidos en la carpeta de elementos.
Selecciona tu dispositivo Coordinador de objetivos en el esquematizador. En el panel Detalles, establece RootProp como tu elemento. En este ejemplo, RootProp se establece como Coastal Buoy 02B.
En el panel Detalles, expande Destination. Como Destination es de tipo
transform, se compone de Scale, Rotation y Translation. Para mover el elemento, solo tienes que cambiar Translation, así que expande esa opción. Establece el campo que termina en X en 5000.0.Al probar el código, es buena idea hacer cambios grandes en los valores para que los efectos sean obvios. Los cambios pequeños pueden hacer que sea difícil saber si tu código está haciendo lo que esperas.
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} # Where the marker will be moved toHaz clic en Verse, luego en Compilar código de Verse y, por último, en Abrir sesión. Por último, haz clic en Iniciar partida. Deberías ver cómo se mueve tu elemento.
Elementos padre y estructuras
Ahora tienes un elemento moviéndose por tu nivel, pero el verdadero objetivo es mover un dispositivo Indicador del mapa para que los jugadores puedan utilizarlo como punto de ruta. Sigue estos pasos para añadir un elemento de construcción y un dispositivo Indicador del mapa a tu nivel y fijarlo al elemento de construcción.
Haz clic con el botón derecho del ratón dentro del explorador de contenido para abrir el menú contextual.
Selecciona Clase de Blueprint en el menú contextual.
En la ventana Escoger clase padre, haz clic en Elemento de construcción.
Aparecerá una nueva clase Blueprint en el Explorador de contenido. Cámbiale el nombre a ObjetoConstrucción.
Arrastra el elemento de construcción a tu nivel. Este elemento no tiene malla, por lo que solo verás su gizmo de transformación.
En el esquematizador, arrastra el dispositivo Indicador del mapa hasta el elemento de construcción. Esto hace que el elemento de construcción sea el padre del dispositivo Indicador del mapa. Ahora, cuando el elemento de construcción se mueve, el dispositivo Indicador del mapa se mueve con él.
Ya sabes cómo crear un dispositivo utilizando Verse, pero también puedes crear archivos de Verse que no tengan dispositivos propios.
Crea un nuevo archivo de Verse y nómbralo objective_marker. Este archivo no creará un dispositivo. En su lugar, contendrá la definición de una estructura (
struct) que se expondrá al dispositivo Verse que creaste anteriormente.Empieza declarando una
structllamada objective_marker. Tendrá dos miembros:RootPropyMapIndicator. Ambos deben tener el especificador@editable.Verseobjective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
Métodos de extensión y argumentos con nombre
Declara un único método, MoveMarker, que moverá el miembro RootProp y su dispositivo Indicador del mapa adjunto. Este método introduce dos características del lenguaje: los métodos de extensión y los argumentos con nombre.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =Métodos de extensión: estás añadiendo el método
MoveMarker()a la estructuraobjective_marker. Un método de extensión se declara utilizando paréntesis que rodean un identificador y un tipo separados por dos puntos. En este caso:(Marker : objective_marker).Argumentos con nombre: el segundo argumento
?OverTimeutiliza el signo?para indicar que debe nombrarse en la llamada a la funciónMoveMarker. Esto ayuda a cualquier programador que lea o escriba una llamada aMoveMarkera entender qué hace el argumentofloat.
MoveMarker() llamará a uno de los dos métodos de la API de elementos: TeleportTo[] que has utilizado antes o MoveTo(). Crea un bloque if..else para comprobar si el parámetro OverTime es mayor que 0.0. Si lo es, llama a MoveTo(). Esto hará que tu objetivo se desplace a su siguiente ubicación durante el periodo de tiempo que especifiques, en lugar de teletransportarse instantáneamente.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]Si compilas el código ahora, debería funcionar, pero no verás un nuevo dispositivo en la carpeta CreativeDevices del explorador de contenido. Esto se debe a que objective_marker es una struct, no una clase que hereda de creative_device.
Actualización del dispositivo Coordinador de objetivos
Ahora que tienes un nuevo tipo al que hacer referencia, tienes que actualizar el objective_coordinator_device para que haga referencia a él.
Elimina la propiedad
RootPropy sustitúyela por una propiedad llamadaPickupMarkerde tipoobjective_marker. Este es el tipo que has creado.MoveMarker()requiere un argumento de tipofloat, así que créalo como una propiedad editable llamadaMoveTime.Elimina la llamada a
TeleportTo[]. En su lugar, llama al métodoMoveMarker()que creaste paraobjective_marker. Requiere el argumento con nombre?OverTime.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{} # How much time the marker should take to reach its new location
Compila este código y comprueba los detalles del dispositivo Coordinador de objetivos. Deberías ver las propiedades PickupMarker y MoveTime, y PickupMarker debería contener RootProp y MapIndicator.
Establece el campo RootProp como BuildingProp, y el campo MapIndicator como Map Indicator Device.
Compila tu código y haz clic en Abrir sesión. Deberías ver un marcador en tu minimapa que empieza a moverse poco después de que empiece tu partida. Pruébalo con
MoveTimeajustado a distintos valores, incluido0.0. Piensa qué movimiento sería el más adecuado para las distintas situaciones.
GetPlayers() y ActivateObjectivePulse()
Hay una forma de dar a tus jugadores un poco más de ayuda para llegar a su siguiente objetivo. Se llama pulso objetivo y cuando está activo muestra una línea de puntos que se mueve desde el jugador hacia el dispositivo Indicador del mapa. Sigue las instrucciones que aparecen a continuación para añadir un pulso objetivo a tu dispositivo Coordinador de objetivos.
El método que necesitas para activar el pulso objetivo se llama ActivateObjectivePulse() y requiere un argumento de tipo agent. Empieza creando el método para obtener la instancia de agent que representa a tu personaje jugador.
Declara una función llamada
FindPlayer()establecida en<private>, con un valor de retorno devoid.Obtén una matriz de todos los jugadores de tu nivel con
Self.GetPlayspace().GetPlayers(). Guarda la matriz en una variable llamadaAllPlayers.VerseFindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()Para obtener la referencia al único jugador de tu nivel, asigna el primer elemento de la matriz a su propia variable. Acceder a una matriz es una expresión falible, así que colócalo en una expresión
if.Verseif (FirstPlayer := AllPlayers[0]):Como asignar tu
playera una variable podría fallar, te conviene utilizar una variable de tipo option cuando hagas referencia al jugador en tu código. Declara una variable de jugador opcional?player. Debe ir con tus otras variables de miembros.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{}Establece tu nueva variable y crea un bloque
elsecon una expresiónPrint()que te avise si no se ha encontrado un jugador. Tu funciónFindPlayer()ya está completa.VerseFindPlayer<private>() : void = # Since this is a single player experience, the first player [0] # should be the only one available. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Player found")
De vuelta a la función OnBegin(), tienes que hacer dos cambios más:
Llama a tu función
FindPlayer().VerseOnBegin<override>()<suspends> : void = FindPlayer()Tras tu llamada a
MoveMarker(), utiliza otra expresiónifpara establecer tu variable opcional de jugador en una nueva variable, y pásala como argumento aPickupMarker.MapIndicator.ActivateObjectivePulse()Verseif (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Si ejecutas tu código ahora, deberías ver el pulso objetivo apuntando desde tu personaje a la ubicación del marcador de objetivo en el nivel.
Secuencias de comandos completas
Objective_marker.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Devices/CreativeAnimation }
objective_marker<public> := struct<concrete>:
# The prop that will be moved
@editable
RootProp<public> : creative_prop = creative_prop{}
Objective_coordinator_device.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Playspaces }
using { /UnrealEngine.com/Temporary/SpatialMath }
objective_coordinator_device<public> := class<concrete>(creative_device):
var PlayerOpt<private> : ?player = false
@editable
Por tu cuenta
Recuerda que el código de movimiento que has escrito aquí sirve para cualquier elemento. Si puedes hacer que un elemento móvil sea el padre de un dispositivo, ese dispositivo se moverá con él. Prueba a mover otros elementos y dispositivos, y a ver si se te ocurren otros juegos que puedan utilizarlos.
Siguientes pasos
Si estás utilizando esta guía para construir el juego de recogida y entrega, tu siguiente paso es aprender a crear la función Cronómetro de cuenta atrás.