Gli indicatori di obiettivo sono utilizzati in molti giochi per guidare il giocatore verso l'obiettivo o punto di interesse successivo. In questo tutorial imparerai a creare un indicatore di obiettivo riutilizzabile con il dispositivo Indicatore mappa e Verse.
Funzionalità del linguaggio Verse utilizzate
-
struct
: puoi raggruppare variabili di tipi diversi in una struttura. -
Metodo di estensione: un tipo speciale di funzione che agisce come membro di una classe o tipo esistente, ma non richiede la creazione di una nuova sottoclasse. In questa guida, imparerai a creare un metodo di estensione per una struttura.
-
argomento con nome: un argomento trasmesso a una chiamata di funzione con il nome di parametro specificato.
API Verse utilizzate
-
API oggetto scenografico: tale API fornisce metodi per il movimento degli oggetti scenografici.
-
Proprietà modificabili: varie proprietà utilizzate sia per fare riferimento ai dispositivi sia per aggiornare i valori variabili per test rapidi.
Istruzioni
Segui questi passaggi per imparare a configurare un indicatore di obiettivo in grado di spostarsi su più obiettivi o punti di interesse. Gli script completi sono inclusi come riferimento alla fine di questa guida.
Configurazione del livello
Questo esempio utilizza i seguenti oggetti scenografici e dispositivi.
-
1 oggetto scenografico di costruzione: un oggetto scenografico che sarà utilizzato per spostare il dispositivo indicatore mappa.
-
1 dispositivo indicatore mappa: un dispositivo che visualizzerà gli indicatori personalizzati sulla minimappa e sulla mappa panoramica.
-
1 dispositivo pedana di generazione giocatore: da aggiungere vicino all'oggetto scenografico in modo che il giocatore sia generato accanto a esso.
Utilizzo dell'API oggetto scenografico
La prima operazione da eseguire per muovere un dispositivo con Verse è quella di spostare un oggetto con l'API oggetto scenografico. Segui questi passaggi per spostare un oggetto scenografico nel tuo livello:
-
Crea un nuovo dispositivo Verse denominato objective_coordinator_device.
-
Nelle espressioni predefinite
using
all'inizio del file Verse, aggiungi un'espressioneusing
per il moduloSpatialMath
. Questo modulo contiene il codice che ti servirà per spostare gli oggetti scenografici.using { /UnrealEngine.com/Temporary/SpatialMath }
-
Aggiungi due proprietà modificabili:
-
Una costante
creative_prop
denominataRootProp
per memorizzare un riferimento all'oggetto mobile. -
Una costante
transform
denominataDestination
per memorizzare la posizione in cui si sposterà l'oggetto scenografico.
objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
-
-
Eseguendo questo codice e trascinando objective_coordinator_device nel tuo livello, potrai visualizzare le due proprietà nel pannello Dettagli.
-
Il metodo
TeleportTo[]
è ciò che sposta effettivamente l'oggetto scenografico. Chiamalo in un'espressioneif
e utilizza le parentesi quadre al posto delle tonde poichéTeleportTo[]
è un'espressione fallibile. L'elementoif
crea un contesto di errore.if(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Oggetto scenografico spostato") else: Print("Oggetto scenografico non spostato")
-
Gli argomenti di
TeleportTo[]
sono Traslazione e Rotazione. Entrambi vengono forniti dalla proprietà Destinazione. -
Torna all'editor e trascina un oggetto scenografico da Fortnite > Gallerie > Oggetti scenografici in Esplora contenuti. Quello utilizzato in questa guida è chiamato Coastal Buoy 02B, ma è idoneo qualsiasi altro della cartella Oggetti scenografici.
-
Seleziona il tuo dispositivo coordinatore degli obiettivi nell'Outliner. Nel pannello Dettagli, imposta RootProp sul tuo oggetto scenografico. In questo esempio, RootProp è impostato su Coastal Buoy 02B.
-
Nel pannello Dettagli, espandi Destinazione. Dal momento che **Destinazione** rappresenta un tipo
transform
, è caratterizzata da vari parametri quali **Scala**, Rotazione e Traslazione. Per spostare l'oggetto scenografico, devi soltanto modificare Translazione e quindi espanderlo. Imposta il campo che termina con X su 5000.0.Quando testi il codice, ti consigliamo di applicare modifiche sostanziali ai valori in modo che gli effetti siano ovvi. Con piccole modifiche, non potrai sapere se il tuo codice viene eseguito come previsto.
using { /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{} # Posizione in cui verrà spostato l'indicatore @editable Destination<public> : transform = transform{} OnBegin<override>()<suspends> : void = if(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Oggetto scenografico spostato") else: Print("Oggetto scenografico non spostato")
-
Fai clic su Verse, poi su Compila codice Verse, quindi su Avvia sessione. Infine, fai clic su Avvia il gioco. Devi vedere il tuo oggetto scenografico muoversi.
Genitore e strutture
Ora hai un oggetto scenografico mobile nel tuo livello, ma il vero scopo è spostare un dispositivo indicatore mappa in modo che i giocatori possano utilizzarlo come punto di riferimento. Segui questi passaggi per aggiungere un oggetto scenografico di costruzione e il dispositivo indicatore mappa al tuo livello e associarlo all'oggetto scenografico di costruzione.
-
Fai clic con il tasto destro in Esplora contenuti per aprire il menu contestuale.
-
Seleziona Classe Blueprint dal menu contestuale
-
Nella finestra Scegli classe genitore, fai clic su Oggetto scenografico di costruzione.
-
Una nuova classe Blueprint verrà visualizzata in Esplora contenuti. Rinominala BuildingProp.
-
Trascina l'oggetto scenografico di costruzione nel tuo livello. Dal momento che questo oggetto non ha alcuna mesh, visualizzerai solo il suo gizmo trasformazione.
-
Nell'Outliner, trascina il dispositivo indicatore mappa sull'oggetto scenografico di costruzione. Ciò, fa sì che l'oggetto scenografico di costruzione diventi il genitore del dispositivo indicatore mappa. D'ora in avanti ogni volta che l'oggetto scenografico si sposterà, il dispositivo indicatore mappa si muoverà insieme di pari passo.
Oltre a creare un dispositivo con Verse, puoi anche creare file Verse che non hanno dispositivi propri.
-
Crea un nuovo file Verse e nominalo objective_marker. Tale file non creerà un dispositivo. Includerà invece la definizione di una
struct
da mostrare al dispositivo Verse creato in precedenza. -
Inizia dichiarando una
struct
con il nome objective_marker. Avrà due membri:RootProp
eMapIndicator
. Entrambi devono avere lo specificatore@editable
.objective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
Metodi di estensione e argomenti con nome
Dichiara un unico metodo, MoveMarker
, che sposterà il membro RootProp
e il dispositivo Indicatore mappa associato. Questo metodo introduce due funzioni caratteristiche del linguaggio: i metodi di estensione e gli argomenti con nome.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
-
Metodi di estensioni: aggiungi il metodo
MoveMarker()
alla strutturaobjective_marker
. Un metodo di estensione viene dichiarato utilizzando parentesi tonde che delimitano un identificatore e un tipo separati da due punti. In questo caso:(Marker : objective_marker)
. -
Argomenti con nome: il secondo argomento
?OverTime
utilizza?
per indicare che deve essere nominato nella chiamata della funzioneMoveMarker
. Questo aiuta gli sviluppatori che leggono o scrivono una chiamata aMoveMarker
a capire come si comporta l'argomentofloat
.
MoveMarker() chiamerà uno dei due metodi dell'API oggetto TeleportTo[]
che hai utilizzato in precedenza, o MoveTo()
. Crea un blocco if..else
per verificare se il parametro OverTime
è maggiore di 0.0
. Se lo è, chiama MoveTo()
. Ciò farà sì che il tuo obiettivo si sposti nella posizione successiva nel periodo di tempo da te specificato, invece di teletrasportarsi istantaneamente.
(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]
Compilando il codice ora, potrai già ottenere i risultati desiderati senza però vedere alcun nuovo dispositivo nella cartella Dispositivi creativi di Esplora contenuti. Ciò è dovuto al fatto che objective_marker è una struct
, non una classe che eredita da creative_device
.
Aggiornamento del dispositivo coordinatore degli obiettivi
Ora che hai un nuovo tipo a cui fare riferimento, devi aggiornare il campo objective_coordinator_device in modo da attivarlo.
-
Elimina la proprietà
RootProp
e sostituiscila con una proprietàPickupMarker
di tipoobjective_marker
. Questo è il tipo che hai creato. -
MoveMarker() richiede un argomento di tipo
float
, quindi crealo come una proprietà modificabile chiamataMoveTime
. -
Elimina la chiamata a
TeleportTo[]
. Chiama invece il metodoMoveMarker()
che hai creato perobjective_marker
. Tale elemento richiede l'argomento con nome?OverTime
.
objective_coordinator_device<public> := class<concrete>(creative_device):
@editable
PickupMarker<public> : objective_marker = objective_marker{}
# Posizione in cui verrà spostato l'indicatore
@editable
Destination<public> : transform = transform{}
# Tempo impiegato dall'indicatore per raggiungere la nuova posizione
@editable
MoveTime<public> : float = 0.0
OnBegin<override>()<suspends> : void =
PickupMarker.MoveMarker(Destination, ?OverTime := MoveTime)
Compila questo codice e verifica attentamente i dettagli del dispositivo coordinatore degli obiettivi. Devi visualizzare le proprietà PickupMarker e MoveTime e PickupMarker deve contenere parametri RootProp e MapIndicator.
-
Imposta il campoRootProp su BuildingProp e il campo MapIndicator su Dispositivo indicatore mappa.
-
Compila il tuo codice and fai clic su Avvia sessione. Devi visualizzare un indicatore sulla minimappa, che si sposta brevemente dopo l'inizio del gioco. Testalo con
MoveTime
impostato su diversi valori compreso0.0
. Considera quali possono essere i movimenti migliori per diversi scenari.
GetPlayers() e ActivateObjectivePulse()
Esiste un'opzione specifica che consente di aiutare i giocatori a raggiungere l'obiettivo successivo. Si chiama impulso obiettivo e quando è abilitata visualizza una linea punteggiata che parte dal giocatore fino al dispositivo indicatore mappa. Per aggiungere un impulso obiettivo al tuo coordinatore degli obiettivi, segui le istruzioni seguenti.

Il metodo che consente di attivare l'impulso oggettivo si chiama ActivateObjectivePulse()
e richiede un argomento di tipo agent
. Inizia creando tale metodo per ottenere un'istanza di agent
che rappresenti i personaggi dei tuoi giocatori.
-
Dichiara una funzione chiamata
FindPlayer()
impostata su<private>
, con un valore di ritornovoid
. -
Ottieni una matrice di tutti i giocatori del tuo livello con
Self.GetPlayspace().GetPlayers()
. Memorizza l'array generato in una variabile chiamata AllPlayers`.FindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()
-
Per ottenere il riferimento a un solo giocatore nel tuo livello, assegna il primo elemento dell'array alla sua variabile. L'accesso a un array è un'espressione fallibile, inseriscila in un'espressione
if
.if (FirstPlayer := AllPlayers[0]):
-
Dal momento che l'assegnazione di un
player
a una variabile può non riuscire, ti suggeriamo di utilizzare una variabile di tipooption
quando fai riferimento al giocatore nel tuo codice. Dichiara la variabile giocatore opzionale?player
. Tale variabile deve corrispondere alle altre variabili membro.objective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # Posizione in cui verrà spostato l'indicatore @editable Destination<public> : transform = transform{} # Tempo impiegato dall'indicatore per raggiungere la nuova posizione @editable MoveTime<public> : float = 0.0
-
Imposta la tua nuova variabile e crea un blocco
else
con un'espressionePrint()
che ti informerà se un giocatore non è stato trovato. La tua funzioneFindPlayer()
è ora pronta.FindPlayer<private>() : void = # Poiché si tratta di un'esperienza per giocatore singolo, il primo giocatore [0] # deve essere l'unico disponibile. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Giocatore trovato") else: # Registra un errore se non riusciamo a trovare un giocatore. Print("Giocatore non trovato")
Tornando alla funzione OnBegin()
, devi apportare altre due modifiche:
-
Chiama la funzione
FindPlayer()
.OnBegin<override>()<suspends> : void = FindPlayer()
-
Dopo aver chiamato
MoveMarker()
, utilizza un'altra espressioneif
per impostare la variabile opzionale del giocatore e trasmettila come argomento aPickupMarker.MapIndicator.ActivateObjectivePulse()
.if (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Se esegui il codice ora, devi vedere l'impulso obiettivo diretto dal personaggio alla posizione dell'indicatore di obiettivo del livello.
Script completi
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>:
# L'oggetto scenografico che verrà spostato
@editable
RootProp<public> : creative_prop = creative_prop{}
# Il figlio dell'oggetto scenografico che verrà spostato
@editable
MapIndicator<public> : map_indicator_device = map_indicator_device{}
# Un metodo di estensione per objective_marker
# Il simbolo ? davanti a OverTime specifica che si tratta di un argomento con nome
(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]
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
PickupMarker<public> : objective_marker = objective_marker{}
# Posizione in cui verrà spostato l'indicatore
@editable
Destination<public> : transform = transform{}
# Tempo impiegato dall'indicatore per raggiungere la nuova posizione
@editable
MoveTime<public> : float = 0.0
OnBegin<override>()<suspends> : void =
FindPlayer()
PickupMarker.MoveMarker(Destination, ?OverTime := MoveTime)
# Se il giocatore non è impostato su falso, attiva l'impulso dell'obiettivo per il giocatore trovato.
if (FoundPlayer := PlayerOpt?):
PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
FindPlayer<private>() : void =
# Poiché si tratta di un'esperienza per giocatore singolo, il primo giocatore [0]
# deve essere l'unico disponibile.
AllPlayers := Self.GetPlayspace().GetPlayers()
if (FirstPlayer := AllPlayers[0]):
set PlayerOpt = option{FirstPlayer}
Print("Giocatore trovato")
else:
# Registra un errore se non riusciamo a trovare un giocatore.
Print("Giocatore non trovato")
In autonomia
Il codice di movimento che hai scritto qui funziona per qualsiasi oggetto scenografico. Se riesci a rendere un oggetto scenografico in movimento il genitore di un dispositivo, quest'ultimo si muoverà con esso. Prova a muovere altri oggetti scenografici e dispositivi e valuta in che modo possono essere utilizzati in altri giochi.
Passaggi successivi
Se hai consultato questa guida per compilare un gioco di raccolta/consegna, il passaggio successivo è approfondire come creare una funzione di Conto alla rovescia.