L'invisibilità degli Infiltrati rappresenta un problema piuttosto peculiare dalla prospettiva del team dei Difensori. Come fanno infatti i Difensori a identificare un giocatore invisibile che potrebbe correre verso la base con il loro obiettivo? Per risolvere questo problema, puoi utilizzare un elemento di aiuto visivo, in questo caso un oggetto scenografico, per mostrare ai Difensori dove si trova l'Infiltrato.
Segui i passaggi seguenti per imparare come creare un oggetto che fluttua sopra la testa di un giocatore quando è in possesso di un obiettivo.
Creazione del dispositivo di Gestione degli oggetti conquistabili
- Crea un nuovo dispositivo Verse denominato item_capture_manager utilizzando Verse Explorer e trascinalo nel livello.
- All'inizio del file
item_capture_manager
:- Aggiungi
using { /UnrealEngine.com/Temporary/SpatialMath }
per accedere alla structvector3
. Ti tornerà utile per sapere dove teletrasportare gli indicatori che fluttuano sopra la testa del giocatore. Aggiungi ancheusing { /Fortnite.com/Characters }
per accedere afort_character
di un giocatore.using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /Fortnite.com/Characters } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath }
- Aggiungi
- Nella definizione della classe
item_capture_manager
, aggiungi i seguenti campi:- Un array modificabile di dispositivi Generatore oggetti conquistabili denominato
CaptureItemSpawners
. Questo array contiene il dispositivo Generatore oggetti conquistabili per gli Infiltrati.item_capture_manager := class(creative_device): Logger:log = log{Channel := triad_item_capture_log_channel} # Generatore di oggetti di cattura che genera gli oggetti da catturare. @editable CaptureItemSpawner:capture_item_spawner_device = capture_item_spawner_device{}
- Un oggetto scenografico di Fortnite Creativo modificabile denominato
CaptureItemIndicator
. Si tratta dell'oggetto scenografico che fluttua sopra la testa dell'Infiltrato quando è in possesso dell'obiettivo.# Generatore di oggetti di cattura che genera gli oggetti da catturare. @editable CaptureItemSpawner:capture_item_spawner_device = capture_item_spawner_device{} # Un oggetto scenografico che fluttua sopra la testa di un giocatore quando è in possesso dell'oggetto # del CaptureItemSpawner. @editable CaptureItemIndicator:creative_prop = creative_prop{}
- Un dispositivo Indicatore mappa modificabile denominato
MapIndicator
. Sarà posizionato sotto il CaptureItemSpawner del livello e mostrerà sulla mappa dove si trovano gli obiettivi di ogni team.# Un oggetto scenografico che fluttua sopra la testa di un giocatore quando è in possesso dell'oggetto # del CaptureItemSpawner. @editable CaptureItemIndicator:creative_prop = creative_prop{} # Indicatore che mostra sulla mappa dove si trovano gli obiettivi di ogni team @editable MapIndicator:map_indicator_device = map_indicator_device{}
- Due valori float modificabili
UpdateRateSeconds
eVerticalOffset
. Il primo valore controlla la velocità di modifica della posizione diCaptureItemIndicator
, mentre il secondo controlla la distanza di fluttuazione dalla testa del giocatore diCaptureItemIndicator
.# Indicatore che mostra sulla mappa dove si trovano gli obiettivi di ogni team @editable MapIndicator:map_indicator_device = map_indicator_device{} # Frequenza di aggiornamento della posizione del CaptureItemIndicator. @editable UpdateRateSeconds:float = 0.15 # A che altezza sopra la testa del giocatore fluttua l'indicatore CaptureItemIndicator. @editable VerticalOffset:float = 180.0
-
- Un dispositivo Messaggio HUD modificabile denominato
ItemGrabbedMessageDevice
. Ogni volta che viene raccolto un obbiettivo, invia un messaggio a tutti i giocatori. ~~~(verse) # A che altezza sopra la testa del giocatore fluttua l'indicatore CaptureItemIndicator. @editable VerticalOffset:float = 180.0
# Visualizza un messaggio quando un giocatore afferra un oggetto conquistabile. @editable ItemGrabbedMessageDevice:hud_message_device = hud_message_device{} ~~~
- Un dispositivo Messaggio HUD modificabile denominato
- Un dispositivo Gestione punteggio modificabile denominato
ScoreManagerDevice
. Assegna un punteggio a un team ogni volta che un giocatore cattura un obiettivo# Visualizza un messaggio quando un giocatore afferra un oggetto conquistabile. @editable ItemGrabbedMessageDevice:hud_message_device = hud_message_device{} # Assegna un punteggio a un giocatore quando cattura l'oggetto. @editable ScoreManagerDevice:score_manager_device = score_manager_device{}
- Un float modificabile denominato
ReturnTime
. Se l'oggetto catturato impiega un certo tempo per ritornare al CaptureItemSpawner, devi monitorare la durata di questo intervallo per determinare il momento esatto in cui riportare gli indicatori al CaptureItemSpawner.
- Un array modificabile di dispositivi Generatore oggetti conquistabili denominato
- Aggiungi un nuovo metodo
FollowCharacter()
alla definizione della classeitem_capture_manager
. Questo metodo prende unfort_character
e ne segue i movimenti utilizzando gli indicatori posizionati sopra la testa. Aggiungi lo specificatore<suspends>
a questa funzione per generare uno di questi per un giocatore ogni volta che sta tenendo un obiettivo.# Fa sì che il CaptureItemIndicator sia mostrato sempre sopra la testa del giocatore. # Viene eseguito durante il loop di aggiornamento per CaptureItemIndicator e verifica se il giocatore # cattura l'oggetto, rilascia l'oggetto o viene eliminato. FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Funzione FollowCharacter generata correttamente")
Esecuzione di una gara mantenendo l'obiettivo
È importante pensare agli scenari possibili che caratterizzano la cattura degli obiettivi da parte del giocatore. Il giocatore può:
- Muoversi, in tal caso devi aggiornare continuamente il tuo CaptureItem e indicatori mappa in base alla posizione del giocatore. Questo può avvenire in loop.
- Catturare l'obiettivo, in tal caso devi spostare i tuoi indicatori in modo che ritornino al CaptureItemSpawner in un punto fuori dalla vista dei giocatori dal momento che non deve risultare visibile se non una volta preso.
- Abbandonare l'obiettivo o essere eliminato, in questo caso gli indicatori devono rimanere dove l'oggetto è stato abbandonato e tornare al CaptureItemSpawner quando l'oggetto di cattura vi fa ritorno.
Per ottenere questi scenari, configura un'espressione race. Utilizzando un'espressione race
per gli scenari descritti, puoi continuare ad aggiornare la posizione degli indicatori mentre attendi che il giocatore abbandoni o catturi l'obiettivo.
- Aggiungi un'espressione
race
aFollowCharacter()
. Configura la gara traloop
,Await()
per l'eventoItemCapturedEvent
diCaptureItemSpawner
,Await()
per l'eventoItemCapturedDroppedEvent
diCaptureItemSpawner
eAwait()
per l'eventoEliminatedEvent()
diFortCharacter
.FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Funzione FollowCharacter generata correttamente") race: loop: CaptureItemSpawner.ItemCapturedEvent.Await() CaptureItemSpawner.ItemDroppedEvent.Await() FortCharacter.EliminatedEvent().Await()
- Nel
loop
, ottieni la posizione diFortCharacter
e memorizzala in una variabileTransform
.loop: Transform := FortCharacter.GetTransform()
- Ora genera un
MoveTo()
per spostare siaCaptureItemIndicator
cheMapIndicator
in base alla traslazione, alla rotazione e alVerticalOffset
diTransform
impostati in precedenza per il periodo di tempoUpdateRateSeconds
. VuoiSpawn{}
entrambe le funzioniMoveTo()
in modo cheCaptureItemIndicator
siaMapIndicator
si muovano esattamente nello stesso momento, invece di aspettare il completamento dell'espressione dell'altro. Poiché la traslazione corrisponde a unvector3
composto da coordinateX
,Y
eZ
, dovrai inserireVerticalOffset
in un nuovovector3
. PoichéVerticalOffset
rappresenta la distanza verticale dalla testa del giocatore, impostalo come valoreZ
delvector3
.loop: Transform := FortCharacter.GetTransform() spawn{CaptureItemIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)}
- Infine, inserisci un evento di sospensione di
0.0
secondi. Questo garantisce che il loop venga eseguito una sola volta a ogni [aggiornamento della simulazione] (verse-glossary#verse-glossary#simulation-update), e non vada fuori controllo generando funzioniMoveTo()
. Il tuo codiceFollowCharacter()
ora deve essere simile al seguente:# Fa sì che il CaptureItemIndicator sia mostrato sempre sopra la testa del giocatore. # Viene eseguito durante il loop di aggiornamento per CaptureItemIndicator e verifica se il giocatore # cattura l'oggetto, rilascia l'oggetto o viene eliminato. FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Funzione FollowCharacter generata correttamente") race: loop: Transform := FortCharacter.GetTransform() spawn{CaptureItemIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} # Vogliamo assicurarci che questo loop venga eseguito una sola volta a ogni aggiornamento della simulazione, perciò inseriamo un evento di sospensione per il tick di gioco. Sleep(0.0) CaptureItemSpawner.ItemCapturedEvent.Await() CaptureItemSpawner.ItemDroppedEvent.Await() FortCharacter.EliminatedEvent().Await() Logger.Print("Obiettivo rilasciato o catturato")
Reimpostazione degli indicatori
- Quando l'oggetto di cattura viene catturato o restituito, devi riportare gli indicatori al
CaptureItemSpawner
in un punto fuori dalla vista. In questo caso, li trasporterai sopra ilCaptureItemSpawner
. Per farlo, aggiungi una funzione denominataReturnIndicators()
alla definizione della classeitem_capture_manager
.# Restituisce la mappa e gli indicatori di cattura di oggetti nelle loro posizioni iniziali sopra i generatori. ReturnIndicators(InAgent:agent):void=
- Ottieni la trasformazione di
CaptureItemSpawner
e salvala in una variabileSpawnerTransform
. Poi genera una funzioneMoveTo() per
CaptureItemIndicatore
MapIndicatorrispetto alla trasformazione e rotazione di
CaptureItemSpawner, aggiungendo un
VerticalOffsetcome hai fatto nell'espressione
loopper posizionarlo sopra
CaptuerItemSpawnwer. Se vuoi che l'oggetto scenografico sia posizionato lontano dalla vista, puoi moltiplicare
VerticalOffsetper un numero alto, in questo caso 10. Il metodo
ReturnIndicators()` completato deve essere simile al seguente:# Restituisce la mappa e gli indicatori di cattura di oggetti nelle loro posizioni iniziali sopra i generatori. ReturnIndicators():void= SpawnerTransform := CaptureItemSpawner.GetTransform() # Teletrasporta al generatore, nascondendo il CaptureItemIndicator e il MapIndicator dietro la mappa in modo che non siano visibili. spawn{CaptureItemIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10.0}, SpawnerTransform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10.0}, SpawnerTransform.Rotation, UpdateRateSeconds)} Logger.Print("Restituiti indicatori per generatore di creature")
Gestione dei giocatori che catturano, abbandonano e conquistano l'obiettivo.
- Aggiungi un nuovo metodo,
OnItemPickedUp()
, alla definizione della classeitem_capture_manager
. Questo metodo prende unagent
e genera un'istanza di FollowCharacter()` per l'agente indicato.# Segnala a tutti i giocatori quando un giocatore cattura l'obiettivo OnItemPickedUp(InAgent:agent):void= Logger.Print("Obiettivo catturato")
- Ottieni
FortCharacter
perInAgent
e genera una funzioneFollowCharacter()
utilizzando lo stessoFortCharacter
. Il metodoOnItemPickedUp()
completato deve essere simile al seguente:# Segnala a tutti i giocatori quando un giocatore cattura l'obiettivo OnItemPickedUp(InAgent:agent):void= Logger.Print("Obiettivo catturato") if(FortCharacter := InAgent.GetFortCharacter[]): ItemGrabbedMessageDevice.Show() spawn{FollowCharacter(FortCharacter)}
- Aggiungi un nuovo metodo,
OnItemCaptured()
, alla definizione della classeitem_capture_manager
. Questo metodo prende l'agent
che ha catturato l'obiettivo.# Quando l'oggetto viene catturato, assegna un punteggio al team che lo ha catturato e restituisce gli indicatori. OnItemCaptured(CapturingAgent:agent):void= Logger.Print("Obiettivo catturato")
- In
OnItemCaptured()
, attiva loScoreManagerDevice
per assegnare il punteggio al team del giocatore che ha conquistato l'obiettivo e chiamaReturnIndicators()
per recuperare gli indicatori.# Quando l'oggetto viene catturato, assegna un punteggio al team che lo ha catturato e restituisce gli indicatori. OnItemCaptured(CapturingAgent:agent):void= Logger.Print("Obiettivo catturato") ScoreManagerDevice.Activate() ReturnIndicators()
- Aggiungi un nuovo metodo,
OnItemDropped()
, alla definizione della classeitem_capture_manager
. Questo metodo prende l'agent
che ha abbandonato l'oggetto.# Quando un giocatore rilascia un oggetto, genera un funzione WaitForReturn() # se il ReturnTime è maggiore di 0. OnItemDropped(InAgent:agent):void= Logger.Print("Obiettivo rilasciato")
- Quando l'obiettivo viene abbandonato, gli indicatori devono rimanere in sua prossimità fino a quando non viene raccolto o torna al
CaptureItemSpawner
. Per sapere quando restituire gli indicatori, utilizzerai la variabileReturnTime
che hai impostato in precedenza. SeReturnTime
è maggiore o uguale a0.0
, dovrai attendere il tempo indicato per restituire gli indicatori. SeReturnTime
è negativo, l'obiettivo non ha un tempo di ritorno, quindi non dovrai spostare gli indicatori. Per spostare indietro gli indicatori, crea una nuova funzione di aiuto denominataWaitForReturn()
, che definirai nel passo successivo.# Quando un giocatore rilascia un oggetto, genera un funzione WaitForReturn() # se il ReturnTime è maggiore di 0. OnItemDropped(InAgent:agent):void= Logger.Print("Obiettivo rilasciato") if(ReturnTime >= 0.0): spawn{WaitForReturn()} else: Logger.Print("L'obiettivo rilasciato non viene restituito")
- Aggiungi un nuovo metodo,
WaitForReturn()
, alla definizione della classeitem_capture_manager
. Questa funzione attende un periodo di tempoReturnTime
, quindi procede alla restituzione se l'obiettivo non è stato raccolto prima del completamento dell'attesa. Aggiungi il modificatore<suspends>
a questo metodo per permettere di applicare la funzioneSleep()
.# Attendi un periodo di tempo ReturnTime, quindi restituisci gli indicatori. WaitForReturn()<suspends>:void= Logger.Print("In attesa della restituzione degli indicatori...")
- La decisione di riportare o meno gli indicatori al loro punto di origine dipende se l'obiettivo è stato raccolto prima della scadenza del
ReturnTime
. Se l'obiettivo è stato raccolto, non è necessario riportare gli indicatori, poiché potrebbero tornare indietro al giocatore in modo inaspettato, causando visualizzazioni anomale. Per gestire questa situazione, utilizzerai una variabile logica il cui valore è uguale al risultato di una gara.# Attendi un periodo di tempo ReturnTime, quindi restituisci gli indicatori. WaitForReturn()<suspends>:void= Logger.Print("In attesa della restituzione degli indicatori...") # Restituisce gli indicatori CaptureItem e Map se l'oggetto di cattura # non è stato raccolto prima dello scadere del tempo. ShouldReturn:logic := race:
- La tua funzione
WaitForReturn()
deve operare in base a due possibili condizioni. Se ilReturnTime
si esaurisce e l'obiettivo ritorna al CaptureItemSpawner, allora devi riportare gli indicatori e la variabileShouldReturn
deve essere impostata sutrue
. In alternativa, se l'obiettivo viene raccolto prima della scadenza delReturnTime
, alloraShouldReturn
deve essere impostato sufalse
. Poiché ognuna di queste condizioni restituisce un valore, eseguirai la gara utilizzando due [blocchi
] (block-in-verse) separati.ShouldReturn:logic := race: block: block:
- Nel primo blocco, chiama
Sleep()
per un periodo di tempoReturnTime
poi restituiscitrue
. Nel secondo,Await()
CaptureItemSpawner.ItemPickedUpEvent
poi restituisci falso. La variabileShouldReturn
sarà ora inizializzata a qualunque di queste condizioni sarà completata per prima.ShouldReturn:logic := race: block: Sleep(ReturnTime) vero block: CaptureItemSpawner.ItemPickedUpEvent.Await() falso
- Se
ShouldReturn
è vero, devi restituire gli indicatori. ChiamaReturnIndicators()
seShouldReturn
valutatrue
. Il tuo codiceWaitForReturn()
completato ora deve essere simile al seguente:# Attendi un periodo di tempo ReturnTime, quindi restituisci gli indicatori. WaitForReturn()<suspends>:void= Logger.Print("In attesa della restituzione degli indicatori...") # Restituisce gli indicatori CaptureItem e Map se l'oggetto di cattura # non è stato raccolto prima dello scadere del tempo. ShouldReturn:logic := race: block: Sleep(ReturnTime) vero block: CaptureItemSpawner.ItemPickedUpEvent.Await() falso if(ShouldReturn?): ReturnIndicators()
- Quindi in
OnBegin()
, sottoscrivi l'eventoItemPickedUpEvent
diCaptureItemSpawner
aOnItemPickedUp()
, l'eventoItemCapturedEvent
aOnItemCaptured()
e l'eventoItemDroppedEvent
aOnItemDropped()
.OnBegin<override>()<suspends>:void= CaptureItemSpawner.ItemPickedUpEvent.Subscribe(OnItemPickedUp) CaptureItemSpawner.ItemCapturedEvent.Subscribe(OnItemCaptured) CaptureItemSpawner.ItemDroppedEvent.Subscribe(OnItemDropped) SpawnerTransform := CaptureItemSpawner.GetTransform()
- Infine, in
OnBegin()
, metti gli indicatori nelle loro posizioni iniziali quando lo script viene eseguito chiamandoMoveTo() per
CaptureItemIndicatore
MapIndicator. Il codice
OnBegin()` ora deve essere simile al seguente:OnBegin<override>()<suspends>:void= CaptureItemSpawner.ItemPickedUpEvent.Subscribe(OnItemPickedUp) CaptureItemSpawner.ItemCapturedEvent.Subscribe(OnItemCaptured) CaptureItemSpawner.ItemDroppedEvent.Subscribe(OnItemDropped) SpawnerTransform := CaptureItemSpawner.GetTransform() # Teletrasporta al generatore, nascondendo il CaptureItemIndicator dietro la mappa, in modo che non sia visibile. CaptureItemIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10.0}, SpawnerTransform.Rotation, UpdateRateSeconds) MapIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10.0}, SpawnerTransform.Rotation, UpdateRateSeconds)
-
Nell'editor, salva lo script, compilalo e trascina il dispositivo nel livello. Scegli un oggetto scenografico appropriato da utilizzare come
CaptureItemIndicator
nel tuo livello. Può essere qualsiasi oggetto a patto che sia sufficientemente visibile. In questo esempio utilizzerai un diamante. Nel pannello Dettagli, assegna CaptureItemSpawner a InfiltratorCaptureSpawner e CaptureItemIndicator all'oggetto scenografico scelto. Assegna anche MapIndicator all'indicatore mappa degli Infiltrati, ItemGrabbedMessageDevice al dispositivo dei messaggi HUD degli Infiltrati e ScoreManagerDevice alla Gestione punteggio degli Infiltrati. Imposta il ReturnTime a un valore negativo, in quanto l'oggetto di cattura degli Infiltrati non viene restituito.Devi anche configurare un'istanza di
item_capture_manager
per gli Attaccanti. Ricordati di cambiare CaptureItemIndicator in un oggetto scenografico diverso dagli oggetti scenografici degli Infiltrati per evitare di confondere visivamente i team e assicurati di assegnare tutti gli altri dispositivi. Imposta il ReturnTime su un numero positivo, in quanto l'oggetto di cattura degli Attaccanti viene restituito dopo un periodo di tempo definito. - Fai clic su Avvia sessione nella barra degli strumenti UEFN per eseguire il playtest del livello. Quando esegui il playtest del tuo livello, il giocatore deve presentare un oggetto scenografico fluttuante sulla sua testa una volta catturato un obiettivo. L'oggetto scenografico deve muoversi con il giocatore e quando abbandona o cattura l'obiettivo deve teletrasportarsi al Generatore oggetti conquistabili.

Passaggio successivo
Nel passaggio successivo di questo tutorial, imparerai a comunicare rapidamente ai giocatori cosa fare durante una partita e su cosa concentrarti per migliorare l'esperienza dei giocatori.