Los marcadores de objetivo se usan en muchos juegos para guiar al jugador hacia el siguiente objetivo o punto de interés. En este tutorial, aprenderás cómo realizar un marcador de objetivo reutilizable con el dispositivo indicador de mapa y Verse.
Funciones usadas del lenguaje Verse
struct: puedes agrupar variables de diferentes tipos en una estructura.
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 la estructura.
argumento con nombre: un argumento que se pasa a una llamada a función con su nombre de parámetro especificado.
API de Verse usadas
API de creative_prop: la API de
creative_propofrece métodos para mover utilería.Propiedades editables: varias propiedades se utilizan tanto para referenciar dispositivos como para actualizar los valores de las variables a fin de realizar pruebas rápidas.
Instrucciones
Realiza estos pasos para aprender cómo configurar un único dispositivo marcador de objetivo que se puede mover a múltiples objetivos o puntos de interés. Al final de esta guía de referencia se incluye la secuencia de comandos completa.
Configuración del nivel
En este ejemplo, se utilizan la utilería y los dispositivos que aparecen a continuación.
1 x utilería de construcción: una utilería que se utilizará para mover el dispositivo indicador de mapa.
1 x dispositivo indicador de mapa: un dispositivo que mostrará marcadores personalizados en el minimapa y una vista general del mapa.
1 x dispositivo de plataforma de aparición de jugador: añádela cerca de la utilería para que el jugador aparezca cerca de ella.
Cómo usar la API de utilería
El primer paso para lograr mover un dispositivo con Verse es mover un objeto con la API Utilería. Realiza estos pasos para mover un objeto en el nivel.
Crea un nuevo dispositivo de Verse llamado objective_coordinator_device.
Bajo las expresiones predeterminadas
usingen la parte superior del archivo de Verse, añade la expresiónusingpara el módulo SpatialMath. Este módulo contiene código de referencia para mover las utilerías.Verseusing { /UnrealEngine.com/Temporary/SpatialMath }Añade dos propiedades editables:
Una constante
creative_propdenominadaRootProppara guardar una referencia a la utilería móvil.Una constante
transformdenominadaDestinopara guardar la ubicación a la que se moverá la utilería.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 el objective_coordinator_device al nivel, verás ambas propiedades en el panel de detalles.
El método
TeleportTo[]es lo que realmente mueve la utilería. Llama dentro de una expresión if y usa corchetes en lugar de paréntesis porqueTeleportTo[]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 para
TeleportTo[]son traslación y rotación. Ambos provienen de la propiedad destino.En el editor, arrastra una utilería de Fortnite > Galerías > Utilería al explorador de contenido. La que usamos en esta guía se denomina Coastal Buoy 02B, pero cualquier elemento de la carpeta Utilería funcionará.
Selecciona el dispositivo coordinador de objetivo en el esquematizador. En el panel de detalles, establece RootProp para tu utilería. En este ejemplo, RootProp se define en Coastal Buoy 02B.
En el panel de detalles, expande Destino. Debido a que Destino es de tipo
transformar, se compone de una escala, rotación y traslación. Para mover la utilería, solo necesitas cambiar la traslación; por lo tanto, expándela. Establece el campo que finaliza con X en 5000.0.Al probar el código, es buena idea realizar grandes cambios a los valores para que los efectos sean obvios. Si los cambios son pequeños, es difícil notar si el código hace lo que debe.
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, después, en Comenzar sesión. Por último, haz clic en Comenzar juego. Podrás ver la utilería moverse.
Base y estructuras
Ahora tienes una utilería que se mueve en el nivel pero el objetivo real es mover un dispositivo indicador de mapa que los jugadores usarán como punto de ruta. Realiza estos pasos para añadir un objeto de construcción y dispositivo indicador de mapa al nivel y adósalo al objeto de construcción.
Haz clic derecho dentro del explorador de contenido para abrir el menú contextual.
Selecciona una clase de blueprint desde el menú contextual.
En la ventana Escoger clase base, haz clic en Utilería de construcción.
Una nueva clase de blueprint aparecerá en tu explorador de contenido. Renómbrala a BuildingProp.
Arrastra el objeto de construcción al nivel. Esta utilería no tiene malla, así que solo verás su artilugio de transformación.
En el esquematizador, arrastra el dispositivo indicador de mapa sobre el objeto de construcción. Esto hace que el objeto de construcción sea base del dispositivo indicador de mapa. Ahora, cuando el objeto de construcción se mueva, el dispositivo indicador de mapa se mueve con él.
Ya sabes cómo crear un dispositivo con Verse, pero también puedes crear archivos de Verse que no tienen sus propios dispositivos.
Crea un nuevo archivo de Verse y denomínalo objective_marker. Este archivo no creará un dispositivo. En cambio, contendrá la definición de una
estructurapara exponer al dispositivo de Verse que creaste anteriormente.Comienza por declarar una
estructuradenominada 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 de mapa adjunto. Este método introduce dos características de lenguaje: métodos de extensión y argumentos con nombre.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =Método de extensión: estás añadiendo el método
MoveMarker()a la estructuraobjective_marker. Los métodos de extensión se declaran con paréntesis que rodean a un identificador y tipo separados por dos puntos. En este caso:(Marker : objective_marker).Argumento con nombre: el segundo argumento
?OverTimeusa el?para indicar que debe nombrarse en la llamada a funciónMoveMarker. Esto ayuda a cualquier desarrollador que lee o escribe una llamada aMoveMarkera comprender qué hace el argumentofloat.
MoveMarker() llamará a uno de dos métodos desde la API de utilería: TeleportTo[], que se usó anteriormente, o MoveTo(). Crea un bloque if..else para probar si el parámetro OverTime es mayor que 0.0. Si lo es, llama a MoveTo(). Esto hará que el objetivo se mueva a la siguiente ubicación en el plazo 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 tener éxito, pero no deberías ver un nuevo dispositivo en la carpeta CreativeDevices del explorador de contenido. Esto se debe a que objective_marker es una estructura, y no una clase que hereda de creative_device.
Cómo actualizar el dispositivo coordinador de objetivo
Ahora que tienes un nuevo tipo al que referenciar, debes actualizar el objective_coordinator_device para referenciarlo.
Elimina la propiedad
RootPropy reemplázala por una propiedad denominadaPickupMarkerdel tipoobjective_marker. Este es el tipo que creaste.MoveMarker()requiere un argumento de tipofloat; así que créalo como una propiedad editable denominadaMoveTime.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 objetivo. Deberías ver las propiedades PickupMarker y MoveTime y PickupMarker debería contener RootProp y MapIndicator.
Define el campo RootProp en BuildingProp y el campo MapIndicator en el dispositivo indicador de mapa
Compila el código y haz clic en Comenzar sesión. Deberías ver un marcador en el minimapa que se mueve poco tiempo después de que comienza el juego. Pruébalo con
MoveTimecon distintos valores, incluido0.0. Considerá cuál movimiento se adapta mejor a los distintos escenarios.
GetPlayers() y ActivateObjectivePulse()
Existe una manera de dar a los jugadores un poco más de ayuda para llegar al siguiente objetivo. Se denomina pulso del objetivo y, cuando está activo, muestra una línea punteada que se mueve desde el jugador hacia el dispositivo indicador de mapa. Realiza lo siguiente para añadir un pulso del objetivo al dispositivo coordinador de objetivo.
El método que necesitas para activar el pulso del objetivo se denomina ActivateObjectivePulse() y requiere un argumento de tipo agente. Primero, crea el método para obtener la instancia de agente que representa el personaje del jugador.
Declara una función denominada
FindPlayer()establecida en<private>con un valor de retornonulo.Obtén una matriz de todos los jugadores en tu nivel con
Self.GetPlayspace().GetPlayers(). Almacena la matriz en una variable denominadaAllPlayers.VerseFindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()Para obtener la referencia al único jugador en el nivel, asigna el primer elemento de la matriz a su propia variable. Acceder a una matriz es una expresión falible, por lo que debes colocarla en una expresión
if.Verseif (FirstPlayer := AllPlayers[0]):Debido a que asignar tu
jugadora una variable podría fallar, debes usar una variable de tipo opción cuando referencies al jugador en tu código. Declara una variable de jugador opcional?player. Debería ir con las otras variables de miembro.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{}Define la nueva variable y crea un bloque
elsecon una expresiónPrint()que te informará si no se encontró un jugador. La 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 en la función OnBegin(), debes realizar dos cambios más:
Llama a la función
FindPlayer().VerseOnBegin<override>()<suspends> : void = FindPlayer()Después de llamar a
MoveMarker(), usa otra expresiónifpara definir la variable de jugador opcional a una nueva variable y pásala como un argumento aPickupMarker.MapIndicator.ActivateObjectivePulse()Verseif (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Si ejecutas el código, deberías ver el pulso del objetivo que señala desde personaje hacia 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 escribiste aquí funciona con cualquier utilería. Si puedes hacer una utilería móvil primaria de un dispositivo, dicho dispositivo se moverá con ella. Intenta mover otras utilerías y dispositivos y prueba si puedes pensar en otros juegos que podría usarlos.
Siguientes pasos
Si usas esta guía para construir un juego de recolección y entrega, el próximo paso es aprender cómo crear un cronómetro de cuenta regresiva.