Questo tutorial si basa sui concetti di statistiche persistenti dei giocatori, quindi vai a dare un'occhiata prima!
Le classifiche sono un punto fermo dei giochi competitivi, consentendo ai giocatori di mostrare le proprie abilità e far conoscere il proprio nome. Aiutano i giocatori a sviluppare un senso di progressione e incoraggiano i giocatori a continuare a tornare in modo da potersi vedere salire in cima.
La Persistenza di Verse fornisce lo strumento che ti consente di creare queste classifiche e aggiungere quel vantaggio competitivo alla tua esperienza. Hai già visto come tenere traccia dei dati persistenti tra le sessioni di gioco nel tutorial sulle statistiche persistenti dei giocatori e come modificare e aggiornare tali dati in base a eventi diversi. Ora applicherai queste conoscenze per imparare a creare classifiche locali complete, ordinare le statistiche dei giocatori e mettere tutto insieme in un gioco di corse!
Funzionalità del linguaggio Verse utilizzate
-
Classe: questo esempio crea una classe Verse persistente che tiene traccia di un gruppo di statistiche per un giocatore.
-
Costruttore: Un costruttore è una funzione speciale che crea un'istanza della classe a cui è associato.
-
Weak_map: Una weak_map è una mappa semplice che non può essere iterata. È necessario che i dati persistenti Verse siano memorizzati in una weak_map.
Configurazione di un livello
Questo esempio utilizza i seguenti oggetti scenografici e dispositivi:
-
3 Dispositivi billboard: Questi mostreranno le statistiche sulla durata di ogni giocatore e le ordinerai in base ai punti vita per mostrare i migliori giocatori nella lobby.
-
3 Dispositivi di riferimento del giocatore: In combinazione con i billboard, i riferimenti dei giocatori daranno un volto al nome dei tuoi migliori giocatori in modo che gli altri giocatori sappiano a chi prestare attenzione durante il gioco.
-
3 Dispositivi punto di controllo: Questi sono i punti di controllo attraverso i quali i giocatori corrono per completare la gara.
-
1 Dispositivo gestione gara: Tiene traccia di quando i giocatori iniziano e terminano la gara e assegna loro punti in base al loro piazzamento finale.
-
1 Dispositivo generatore furgone: Genera il veicolo che utilizzerai durante la gara, ma puoi cambiarlo in qualsiasi veicolo in base alla tua esperienza.
Segui questi passaggi per configurare il livello:
Billboard e riferimenti dei giocatori
Per visualizzare le statistiche dei giocatori, utilizzerai una combinazione di billboard e riferimenti dei giocatori. Ogni billboard mostrerà le statistiche sulla durata di un giocatore, mentre il riferimento del giocatore mostrerà una rappresentazione visiva di quel giocatore. Per aggiungere questi elementi, segui i passaggi:
-
Aggiungi tre dispositivi Riferimento giocatore al tuo livello e posizionali uno accanto all'altro.
-
Per ogni riferimento giocatore, selezionalo nell'Outliner. Nel pannello Dettagli, in Opzioni utente, imposta Colore personalizzato sul colore che desideri rappresenti il primo, il secondo e il terzo giocatore con le migliori prestazioni nella lobby. In questo esempio vengono utilizzati oro, argento e bronzo come colori.
-
Aggiungi tre dispositivi Billboard al tuo livello e posizionane uno davanti a ciascun riferimento giocatore. Li aggiornerai con le statistiche di ogni giocatore usando Verse all'inizio del gioco.
Punti di controllo, furgone e gestione gara
Dato che si tratta di una gara, avrai bisogno di qualcosa con cui gareggiare! Avrai anche bisogno di punti di controllo da attraversare e di una gestione gara per dirigere la gara durante il gioco. Per aggiungere questi elementi, segui i passaggi:
-
Aggiungi tre dispositivi Punto di controllo gara al tuo livello. Posizionali nell'ordine in cui vuoi che i giocatori corrano attraverso di loro. Per ogni punti di controllo, nell'Outliner, assicurati che il Numero punto di controllo corrisponda all'ordine in cui i giocatori viaggiano attraverso i punti di controllo.
-
Aggiungi un dispositivo Gestione gara al tuo livello. Questo gestirà la corsa e indirizzerà i giocatori verso i punti di controllo. Ascolterai il
RaceCompletedEvent()
da questo dispositivo in un secondo momento per sapere quando un giocatore termina la gara. -
Aggiungi un dispositivo Generatore furgone al tuo livello. Un veicolo è facoltativo, ma questa guida utilizza un furgone per adattarsi al Modello speedway e dare ai giocatori qualcosa su cui guidare intorno.
Modifica della tabella delle statistiche
Questo esempio utilizza una versione modificata del file player_stats_table
da statistiche persistenti dei giocatori. Questo sarà simile al file di quell'esempio, con alcune differenze importanti che cambiano l'implementazione.
Segui i passaggi seguenti per creare la tabella delle statistiche dei giocatori:
-
Nella classe
player_stats_table
:-
Rimuovi la statistica
Losses
. -
Cambia la statistica
Score
inPoints
.
# Tiene traccia di diverse statistiche persistenti per ogni giocatore. player_stats_table<public>:= class<final><persistable>: # Versione della tabella delle statistiche attuale. Version<public>:int = 0 # Punti di un giocatore. Points<public>:int = 0 # Numero di vittorie di un giocatore. Wins<public>:int = 0
-
-
Modifica la funzione di costruttore
MakePlayerStatsTable()
nel tuo file per riflettere le statistiche aggiornate.# Crea una nuova player_stats_table con gli stessi valori della player_stats_table. MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table: Version := OldTable.Version Points := OldTable.Points Wins := OldTable.Wins
-
Aggiungi una nuova struttura
player_and_stats
al tuo file player_stats_table.verse. Questa struttura contiene un riferimento a unplayer
e alla sua classeplayer_stats_table
per consentire di utilizzare entrambi i dati nelle funzioni senza doverli recuperare ripetutamente. La tua strutturaplayer_and_stats
completa deve assomigliare a questa:# Struttura per il passaggio di un giocatore e le sue statistiche come argomenti. player_and_stats<public> := struct: Player<public>:player StatsTable<public>:player_stats_table
Gestione delle statistiche
Proprio come in statistiche persistenti dei giocatori, utilizzerai un file manager per gestire e registrare le modifiche alle statistiche per i giocatori.
Segui i passaggi seguenti per creare il file player_stats_manager
modificato.
-
Modifica la firma della funzione di
InitializeAllPlayers()
eInitializePlayer()
inInitializeAllPlayerStats()
eInitializePlayerStat()
. Questi nomi riflettono meglio la loro relazione con la funzioneGetPlayerStat()
. La funzione aggiornata deve essere simile alla seguente:# Inizializza le statistiche per tutti i giocatori attuali. InitializeAllPlayerStats<public>(Players:[]player):void = for (Player : Players): InitializePlayerStat(Player) # Inizializza le statistiche per il giocatore indicato. InitializePlayerStat<public>(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Impossibile inizializzare le statistiche del giocatore")
-
Modifica la firma della funzione di
AddScore()
inAddPoints()
. Quindi rimuovi la funzioneAddLosses()
perché il tuoplayer_stats_table
non contiene più quel valore. Il tuo fileplayer_stats_manager
completato deve essere simile a:# Questo file gestisce the codice di inizializzazione, aggiornamento e restituzione di player_stats_tables # per ogni giocatore. Definisce anche una classe stat_type astratta da usare per l'aggiornamento delle statistiche e il # modulo StatType da usare quando vengono visualizzate le statistiche. using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Restituisci il player_stats_table per l'agente fornito. GetPlayerStats<public>(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{} if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] set PlayerStats = MakePlayerStatsTable(PlayerStatsTable) PlayerStats # Inizializza le statistiche per tutti i giocatori attuali. InitializeAllPlayerStats<public>(Players:[]player):void = for (Player : Players): InitializePlayerStat(Player) # Inizializza le statistiche per il giocatore indicato. InitializePlayerStat<public>(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Impossibile inizializzare le statistiche del giocatore") # Aggiunge ai punti dell'agente e aggiorna entrambe le tabelle delle statistiche # in PlayerStatsManager e il billboard nel livello. AddPoints<public>(Agent:agent, NewPoints:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentPoints := PlayerStatsTable.Points set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Points := CurrentPoints + NewPoints else: Print("Impossibile registrare i punti del giocatore") # Aggiunge alle vittorie dell'agente e aggiorna entrambe le tabelle delle statistiche # in PlayerStatsManager e il billboard nel livello. AddWin<public>(Agent:agent, NewWins:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentWins := PlayerStatsTable.Wins set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Wins := CurrentWins + NewWins else: Print("Impossibile registrare le vittorie del giocatore")
Costruire le classifiche dei giocatori
Per visualizzare i dati dei giocatori nelle tue classifiche, avrai bisogno di alcune cose. Hai bisogno di un modo per aggiornare il testo sui billboard e i giocatori sui dispositivi di riferimento del giocatore. Hai anche bisogno di un modo per ordinare questi dispositivi, poiché vuoi che i migliori giocatori siano i più importanti nella tua classifica. Poiché queste funzioni hanno un obiettivo simile di modificare i dispositivi nel livello, è consigliabile raggruppare le funzioni in un file comune.
Segui i passaggi seguenti per creare funzioni che aggiornano i tuoi dispositivi a livello interno:
-
Crea un nuovo file Verse denominato player_leaderboards.verse. Questo file memorizzerà le funzioni comuni per l'aggiornamento delle classifiche a livello interno.
-
Per il testo sul billboard, utilizzerai un messaggio a cui puoi passare argomenti. Crea un nuovo messaggio denominato
StatsMessage
che accetta unCurrentPlayer
,Points
eWins
, tutti di tipomessage
e restituisce il testo combinato comemessage
.# Messaggio da visualizzare sul billboard. StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message= "{CurrentPlayer}:\n{Points}\n{Wins}"
-
Aggiungi altre tre variabili
message
, una per ciascuno degli input aStatsMessage
. Il messaggioPlayerText
prende unAgent
, il messaggioPointsText
prende i punti di quell'agente e il messaggioWinsText
prende le vittorie di quell'agente.StatsMessage
creerà un messaggio da tutti questi per visualizzare in modo pulito i tuoi dati nel livello.# Messaggio da visualizzare sul billboard. StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message= "{CurrentPlayer}:\n{Points}\n{Wins}" PlayerText<localizes>(CurrentPlayer:agent):message = "Player {CurrentPlayer}" PointsText<localizes>(Points:int):message = "Punti totali {Points}" WinsText<localizes>(Wins:int):message = "{Wins} Vittorie totali"
-
Per aggiornare un billboard, chiama la funzione
UpdateStatsBillboard()
dal tutorial sulle statistiche persistenti dei giocatori. Poiché questa funzione è definita in un file separato dal dispositivo Verse, devi aggiungere unStatsBillboard
come argomento aggiuntivo per specificare quale cartellone pubblicitario si intende aggiornare.# Aggiorna il dispositivo del billboard per visualizzare le statistiche del giocatore specificato. UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void=
-
Innanzitutto, passa le statistiche del giocatore come argomento utilizzando
GetPlayerStats[]
. Non è necessario un riferimento a unplayer_stats_manager
poiché non è più una classe separata. Quindi costruisci un nuovoStatsMessage
utilizzando il giocatore e iPoints
eWins
daCurrentPlayerStats
. Infine, chiamaSetText()
suStatsBillboard
per aggiornare il testo del billboard nel livello interno. La funzioneUpdateStatsBillboard()
completa deve essere simile a questa:# Aggiorna il dispositivo del billboard per visualizzare le statistiche del giocatore specificato. UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void= if: CurrentPlayerStats := GetPlayerStats[Player] then: PlayerStatsText := StatsMessage( PlayerText(Player), PointsText(CurrentPlayerStats.Points), WinsText(CurrentPlayerStats.Wins)) StatsBillboard.SetText(PlayerStatsText)
Ordinare e visualizzare il miglior giocatore
Prima di continuare, è importante considerare come si desidera ordinare questi billboard. Vuoi che vinca il giocatore con il maggior numero di punti o il giocatore con il maggior numero di vittorie? E se volessi ordinare in base a statistiche diverse? Hai bisogno di un metodo per gestire tutto questo e un algoritmo di ordinamento è la risposta. Utilizzando un algoritmo di ordinamento e una funzione di confronto, puoi specificare i criteri in base ai quali vuoi eseguire l'ordinamento. Puoi quindi ordina i billboard e i riferimenti dei giocatori per mostrare i migliori giocatori della tua esperienza. In questo esempio viene utilizzato l'algoritmo unisci ordinamento, ma puoi implementarne uno personalizzato.
Segui i passaggi seguenti per aggiungere il confronto e l'ordinamento ai tuoi billboard e completare l'aggiornamento dei dispositivi nel tuo livello.
-
Torna al file
player_stats_table
, definisci le funzioni di confronto per ognuna delle tue statistiche. Ognuna ha una strutturaplayer_and_stats
Left
eRight
e le confronta in base a una determinata statistica. Queste funzioni hanno i modificatori<decides><transacts>
; se il confronto non riesce, anche la funzione non riesce. Per esempio, dicendoti cheLeft
è inferiore aRight
. Aggiungi una nuova funzione chiamataMorePointsComparison()
al tuo file player_stats_table.verse. Questa funzione controlla se
Left.Pointsè superiore a
Right.Pointse, in caso contrario, non riesce. Se riesce, restituisce
Left`.# Restituisce Left se Left ha più punti di Right. MorePointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:Left= Left.StatsTable.Points > Right.StatsTable.Points A sinistra
-
Copia questa funzione tre volte, una per un confronto a meno punti e due per il confronto delle vittorie. Le tue funzioni di confronto devono avere questo aspetto:
# Restituisce Left se Left ha più punti di Right. MorePointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points > Right.StatsTable.Points A sinistra # Restituisce Left se Left ha meno punti di Right. LessPointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points < Right.StatsTable.Points A sinistra # Restituisce Left se Left ha più podi di destra. MorePodiumsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points > Right.StatsTable.Points A sinistra # Restituisce Left se Left ha meno podi di Right. LessPodiumsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points < Right.StatsTable.Points A sinistra
-
Aggiungi l'algoritmo Ordinamento per fusione. Puoi posizionarlo in un file o modulo separato e provare l'algoritmo sul file di test fornito.
-
Di nuovo in
player_leaderboards
, aggiungi una nuova funzioneUpdateStatsBillboards()
. Questa funzione prende un array di agenti e un array di billboard, li ordina e chiamaUpdateStatsBillboard()
per aggiornare ogni billboard nel livello.# Aggiorna i billboard delle statistiche ordinandoli in base alla quantità di punti lifetime # di ogni giocatore. UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void=
-
In
UpdateStatsBillboards()
, inizializza una nuova variabile di array diplayer_and_stats
chiamataPlayerAndStatsArray
. Imposta pari al risultato di un espressionefor
. Nell'espressionefor
, per ogniagente
, ottieniplayer
di taleagent
e recuperi la suaplayer_stats_table
utilizzandoGetPlayerStats[]
. Poi restituisci una strutturaplayer_and_stats
costruita dalgiocatore
e dalla sua tabella delle statistiche.UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats: Player := Player StatsTable := PlayerStats
-
Per ordinare il tuo
PlayerAndStatsArray
, inizializza una nuova variabileSortedPlayersAndStats
al risultato della chiamataMergeSort()
, passando l'array eMorePointsComparison
. Dopo aver ordinato in un'espressionefor
, itera tramite ogni elemento inSortedPlayerAndStats
, memorizzando l'indice degli elementi in una variabilePlayerIndex
. UtilizzaPlayerIndex
per l'indice nell'arrayStatsBillboards
, poi chiamaUpdateStatsBillboard
passando il giocatore e il billboard per aggiornare. La tua funzioneUpdateStatsBillboards()
completa deve avere questo aspetto:# Aggiorna i billboard delle statistiche ordinandoli in base alla quantità di punti lifetime # di ogni giocatore. UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats: Player := Player StatsTable := PlayerStats # Confronta e ordina i giocatori in base ai loro punti totali che sono il metro di misura # del "miglior" giocatore nella lobby. Qui puoi cambiare la funzione di confronto in base alle # esigenze della tua esperienza. SortedPlayersAndStats := SortingAlgorithms.MergeSort( PlayerAndStatsArray, MorePointsComparison) for: PlayerIndex -> PlayerAndStats : SortedPlayersAndStats StatsBillboard := StatsBillboards[PlayerIndex] do: UpdateStatsBillboard(PlayerAndStats.Player, StatsBillboard)
-
Per aggiornare i tuoi riferimenti dei giocatori, utilizza una funzione molto simile chiamata
UpdatePlayerReferences()
. Questa funzione prende un array diplayer_reference_device
invece dei billboard e, invece di chiamareUpdateStatsBillboard()
alla fine, chiamaRegister()
sul dispositivo di riferimento per ogni giocatore. Copia il tuo codiceUpdateStatsBillboard()
in una nuova funzioneUpdatePlayerReferences()
con queste modifiche. La tua funzioneUpdatePlayerReferences()
completa deve avere questo aspetto:# Aggiorna i dispositivi dei riferimenti dei giocatori ordinandoli in base alla quantità # di punti lifetime di ogni giocatore. UpdatePlayerReferences<public>(Players:[]player, PlayerReferences:[]player_reference_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats: Player := Player StatsTable := PlayerStats # Confronta e ordina i giocatori in base ai loro punti totali che sono il metro di misura # del "miglior" giocatore nella lobby. Qui puoi cambiare la funzione di confronto in base alle # esigenze della tua esperienza. SortedPlayersAndStats := SortingAlgorithms.MergeSort( PlayerAndStatsArray, MorePointsComparison) for: PlayerIndex -> PlayerAndStats : SortedPlayersAndStats PlayerReference := PlayerReferences[PlayerIndex] do: PlayerReference.Register(PlayerAndStats.Player)
Classifiche dei giocatori nel tuo livello
Ora che tutto è configurato, è il momento di mettere in mostra i tuoi giocatori! Crea un dispositivo per assegnare i punti ai giocatori quando interagiscono con il pulsante e ordina i riferimenti dei giocatori e i billboard in modo che i migliori giocatori siano davanti e al centro. Segui questa procedura per creare un dispositivo Verse per provare le classifiche nel tuo livello:
-
Crea un nuovo dispositivo Verse chiamato player_leaderboards_example. Per informazioni sui passaggi, vedi Creare il tuo dispositivo utilizzando Verse.
-
All'inizio della definizione di
player_leaderboards_example class
, aggiungi i seguenti campi:-
Array modificabile dei dispositivi dei riferimenti dei giocatori chiamato
PlayerReferences
. Questi offrono rappresentazioni visive di ogni giocatore nella gara.# Rappresentazioni visive di ogni giocatore. @editable PlayerReferences:[]player_reference_device = array{}
-
Array modificabile dei dispositivi dei billboard chiamato
Leaderboards
. Questi visualizzano statistiche di ogni giocatore su un billboard nel livello.# Billboard che visualizzano le statistiche di ogni giocatore. @editable Leaderboards:[]billboard_device = array{}
-
Dispositivo di Gestione gara modificabile chiamato
RaceManager
. Iscriviti agli eventi dal sistema di Gestione gara per sapere quando un giocatore termina la gara.# Tiene sotto controllo i momenti in cui i giocatori terminano una gara e assegna la vittoria ai giocatori in prima posizione. @editable RaceManager:race_manager_device = race_manager_device{}
-
Intero modificabile chiamato
PlacementRequiredForWin
. Questa è la posizione in cui si deve piazzare un giocatore per ottenere una vittoria.# Posizione minima in cui si deve piazzare un giocatore per ottenere una vittoria. @editable PlacementRequiredForWin:int = 1
-
Array modificabile di interi chiamato
PointsPerPlace
. Questi sono i numeri di punti che ogni giocatore ottiene in base alla posizione.# Numero di punti che i giocatori ottengono in base alla posizione. # Regolalo per assegnare il punteggio che desideri ai tuoi giocatori # in base alla loro posizione. @editable PointsPerPlace:[]int = array{5, 3, 1}
-
Variabile intera chiamata
CurrentFinishOrder
. Questa è la posizione del giocatore che ha completato più recentemente la gara.# Posizione dell'ultimo giocatore che ha completato la gara. # Ai primi tre giocatori che terminano la gara viene assegnata una vittoria. var CurrentFinishOrder:int = 0
-
Assegnazione delle statistiche in base alla posizione
Quando un giocatore termina la gara, aggiorni le sue statistiche in base alla sua posizione. I giocatori che si piazzano in buone posizioni devono ricevere un maggiore numero di punti e a quelli nelle posizioni migliori deve essere assegnata una vittoria.
Per assegnare le statistiche ai giocatori quando terminano una gara, segui questa procedura:
-
Aggiungi una nuova funzione
RecordPlayerFinish()
alla tua definizione della classeplayer_leaderboards_example
. Questa funzione considera il giocatore a cui assegnare le statistiche come un parametro.# Quando un giocatore termina la gara, assegnagli i punti in base alla sua posizione e una vittoria se # la sua posizione è migliore di PlacementRequiredForWin. RecordPlayerFinish(Player:agent):void=
-
In
RecordPlayerFinish()
, ottieni la posizione di questo giocatore tramite il valore attuale diCurrentFinishOrder
in un nuovoint
chiamatoPlayerFinishOrder
. Poi incrementaCurrentFinishOrder
in modo che il giocatore successivo a terminare la gara non abbia la stessa posizione.RecordPlayerFinish(Player:agent):void= PlayerFinishOrder:int = CurrentFinishOrder set CurrentFinishOrder += 1
-
Adesso è il momento di assegnare le statistiche. Per sapere quanti punti assegnare ai giocatori, in un'espressione
if
, indicizza nell'arrayPointsPerPlace
utilizzandoPlayerFinishOrder
. Poi chiamaAddPoints()
per assegnare i punti ai giocatori.set CurrentFinishOrder += 1 if: PointsToAward := PointsPerPlace[PlayerFinishOrder] then: AddPoints(Player, PointsToAward)
-
Se la posizione del giocatore è sufficiente per la vittoria, registra una vittoria nella sua tabella delle statistiche. In un'altra espressione
if
, controlla sePlayerFinishOrder
è inferiore aPlacementRequiredToWin
. In questo caso, chiamaAddWin()
, passa il giocatore e assegnagli una vittoria. La tua funzioneRecordPlayerFinish()
completa deve avere questo aspetto:# Quando un giocatore termina la gara, assegnagli i punti in base alla sua posizione e una vittoria se # la sua posizione è migliore di PlacementRequiredForWin. RecordPlayerFinish(Player:agent):void= PlayerFinishOrder:int = CurrentFinishOrder set CurrentFinishOrder += 1 if: PointsToAward := PointsPerPlace[PlayerFinishOrder] then: AddPoints(Player, PointsToAward) # Se la posizione finale di un giocatore è minore o uguale a PlacementRequiredToWin, # assegnagli una vittoria e registralo nella sua player_stats_table. if: PlayerFinishOrder < PlacementRequiredForWin then: AddWin(Player, 1)
In attesa che i giocatori terminino la gara
Ora che la registrazione delle statistiche è pronta, devi sapere quando un giocatore termina la gara per aggiornare le sue statistiche. Per farlo, ascolti RaceCompletedEvent()
del gestore della gara. Questo evento si verifica ogni volta che un giocatore termina la gara, quindi devi ascoltare in modo continuo in una funzione asincrona.
-
Aggiungi una nuova funzione
WaitForPlayerToFinishRace()
alla tua definizione della classeplayer_leaderboards_example
. Questa funzione prende un giocatore e attende che termini la gara.# Quando un giocatore termina la gara, registra un fine gara nella sua tabella delle statistiche. WaitForPlayerToFinishRace(Player:agent)<suspends>:void=
-
In
WaitForPlayerToFinishRace()
, in un'espressionerace
, avvia due loop. Il primo attende che il giocatore finisca la gara e il secondo gestisce ciò che succede se un giocatore lascia la sessione prima del termine. Se un giocatore esce, non vuoi che il loop continui per sempre, quindi hai bisogno di un modo per uscire da questa situazione.# Quando un giocatore termina la gara, registra un fine gara nella sua tabella delle statistiche. WaitForPlayerToFinishRace(Player:agent)<suspends>:void= race: # Attendi che questo giocatore termini la gara e poi registra il fine gara. loop: # Attendi che questo giocatore esca dal gioco. loop:
-
Nel primo loop, attendi
RaceManager.RaceCompletedEvent
e memorizza il risultato in una variabile chiamataFinishingPlayer
. Dato che questo evento si verifica ogni volta che un giocatore termina la gara, devi verificare che il giocatore che hai memorizzato sia quello che stavi monitorando. ConfrontaFinishingPlayer
e il giocatore che questo loop sta monitorando. Se sono uguali, passa il giocatore aRecordPlayerFinish()
e interrompi il loop# Attendi che questo giocatore termini la gara e poi registra il fine gara. loop: FinishingPlayer := RaceManager.RaceCompletedEvent.Await() if: FinishingPlayer = Player then: RecordPlayerFinish(Player) break
-
Nel secondo loop, attendi l'evento
PlayerRemovedEvent()
dello spazio di gioco. Come prima, ottieni il giocatore che è appena uscito e memorizzalo in una variabile chiamataLeavingPlayer
. Se il giocatore che è appena uscito è il giocatore che questo loop sta aspettando, interrompi il loop. La tua funzioneWaitForPlayerToFinishRace()
completa deve avere questo aspetto:# Quando un giocatore termina la gara, registra un fine gara nella sua tabella delle statistiche. WaitForPlayerToFinishRace(Player:agent)<suspends>:void= race: # Attendi che questo giocatore termini la gara e poi registra il fine gara. loop: FinishingPlayer := RaceManager.RaceCompletedEvent.Await() if: FinishingPlayer = Player then: RecordPlayerFinish(Player) break # Attendi che questo giocatore esca dal gioco. loop: LeavingPlayer := GetPlayspace().PlayerRemovedEvent().Await() if: LeavingPlayer = Player then: break
Collegare il tutto
Quando le tue funzioni sono pronte, devi collegarle ai tuoi dispositivi e iniziare la gara!
Segui questa procedura per collegare la tua logica ai tuoi dispositivi:
-
In
OnBegin()
, inserisci tutti i giocatori nello spazio di gioco utilizzandoGetPlayers()
. Passa questo array aInitializeAllPlayerStats()
per configurareplayer_stats_tables
per ognuno di loro.# Viene eseguito quando il dispositivo viene avviato in un gioco in esecuzione OnBegin<override>()<suspends>:void= # Prendi i giocatori nella gara attuale e crea una player_stat_table # per ognuno di loro. Players := GetPlayspace().GetPlayers() InitializeAllPlayerStats(Players)
-
Chiama
UpdateStatsBillboards()
, passando gli arrayPlayers
eLeaderboards
per aggiornare i billboard nel livello con i dati attuali di ogni giocatore. Poi chiamaUpdatePlayerReferences()
per aggiornare i riferimenti nel livello in modo che corrispondano ai giocatori. Infine, in un'espressionefor
, genera una funzioneWaitForPlayerToFinishRace()
per ogni giocatore. La tua funzioneOnBegin()
completa deve avere questo aspetto:# Viene eseguito quando il dispositivo viene avviato in un gioco in esecuzione OnBegin<override>()<suspends>:void= # Prendi i giocatori nella gara attuale e crea una player_stat_table # per ognuno di loro. Players := GetPlayspace().GetPlayers() InitializeAllPlayerStats(Players) UpdateStatsBillboards(Players, Leaderboards) UpdatePlayerReferences(Players, PlayerReferences) # Attendi che tutti i giocatori terminino la gara. for: Player:Players do: spawn{WaitForPlayerToFinishRace(Player)}
-
Salva il codice e compilalo.
Trascina il dispositivo player_leaderboards_example nel tuo livello. Assegna i riferimenti dei giocatori all'array PlayerReferences, prendendo nota dell'ordine. Il dispositivo nel primo indice deve corrispondere al riferimento del primo giocatore, il secondo indice a quello del secondo giocatore e così via. Fai lo stesso per le classifiche, verificando che siano allineate ai dispositivi di riferimento dei giocatori. Ricorda di assegnare anche il dispositivo di Gestione gara!

Test delle tue classifiche persistenti
Puoi testare i tuoi dati persistenti in una sessione di modifica, ma questi dati verranno ripristinati quando esci e lanci di nuovo la sessione. Affinché i tuoi dati siano persistenti da una sessione all'altra, devi lanciare una sessione di playtest e modificare alcune impostazioni nelle tue Impostazioni dell'isola. Per informazioni sulla configurazione della tua isola per testare i dati persistenti nelle sessioni di modifica e di playtest, dai un'occhiata a Test con i dati persistenti e modifica alcune impostazioni nelle tue Impostazioni dell'isola. Per informazioni sulla configurazione della tua isola per testare i dati persistenti nelle sessioni di modifica e di playtest, dai un'occhiata a Test con i dati persistenti.
Dopo aver configurato la tua sessione, quando vuoi eseguire il playtest del tuo livello, ai giocatori che terminano la gara devono essere assegnati punti in base alla loro posizione. Deve essere assegnata una vittoria se la loro posizione è sufficientemente alta e queste statistiche devono essere persistenti da una sessione di gioco all'altra. I giocatori e le loro statistiche devono essere ordinati con il giocatore con più punti in prima posizione.

In autonomia
Dopo aver completato questa guida, hai imparato come creare le classifiche che visualizzano le statistiche persistenti dei giocatori nel tuo livello. Hai imparato anche come ordinare e aggiornare queste classifiche, verificando che tutti possano vedere chi sono i migliori giocatori. Cerca di adattare questo tutorial alle tue esperienze e metti in mostra il meglio del meglio!
Codice completo
player_stats_table.verse
# Questo file definisce una player_stats_table, una raccolta di statistiche persistenti dei giocatori.
# Contiene anche funzioni per confrontare le tabelle delle statistiche per ognuna delle statistiche per ordinare i giocatori
# durante l'ordinamento.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Struttura per il passaggio di un giocatore e le sue statistiche come argomenti.
player_and_stats<public> := struct:
Player<public>:player
StatsTable<public>:player_stats_table
# Tiene traccia di diverse statistiche persistenti per ogni giocatore.
player_stats_table<public>:= class<final><persistable>:
# Versione della tabella delle statistiche attuale.
Version<public>:int = 0
# Punti di un giocatore.
Points<public>:int = 0
# Numero di vittorie di un giocatore.
Wins<public>:int = 0
# Restituisce Left se Left ha più punti di Right.
MorePointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points > Right.StatsTable.Points
A sinistra
# Restituisce Left se Left ha meno punti di Right.
LessPointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points < Right.StatsTable.Points
A sinistra
# Restituisce Left se ha un numero più elevato di Right.
MoreWinsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points > Right.StatsTable.Points
A sinistra
# Restituisce Left se ha un numero inferiore di vittorie di Right.
LessWinsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points < Right.StatsTable.Points
A sinistra
# Restituisce Left se ha un tempo BestLapTime più lento di Right.
# Questo è al contrario rispetto alle altre statistiche, dato che un tempo sul giro inferiore è meglio.
SlowerLapTimeComparison(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points > Right.StatsTable.Points
A sinistra
# Restituisce Left se ha un tempo BestLapTime più veloce di Right.
# Questo è al contrario rispetto alle altre statistiche, dato che un tempo sul giro inferiore è meglio.
FasterLapTimeComparison(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats=
Left.StatsTable.Points < Right.StatsTable.Points
A sinistra
# Crea una nuova player_stats_table con gli stessi valori della player_stats_table.
MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table:
Version := OldTable.Version
Points := OldTable.Points
Wins := OldTable.Wins
# Mappa i giocatori in una tabella con le loro statistiche.
var PlayerStatsMap:weak_map(player, player_stats_table) = map{}
player_leaderboards.verse
# Questo file contiene il codice che aggiorna billboard, riferimenti dei giocatori e UI sull'isola
# per visualizzare le statistiche dei giocatori dalle loro tabella delle statistiche. Gestisce anche l'aggiunta di vittorie e punti alle
# tabelle delle statistiche dei giocatori.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { PlayerStatistics }
# Messaggio da visualizzare sul billboard.
StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message=
"{CurrentPlayer}:\n{Points}\n{Wins}"
PlayerText<localizes>(CurrentPlayer:agent):message = "Player {CurrentPlayer}"
PointsText<localizes>(Points:int):message = "Punti totali {Points}"
WinsText<localizes>(Wins:int):message = "{Wins} Vittorie totali"
# Aggiorna il dispositivo del billboard per visualizzare le statistiche del giocatore specificato.
UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void=
if:
CurrentPlayerStats := GetPlayerStats[Player]
then:
PlayerStatsText := StatsMessage(
PlayerText(Player),
PointsText(CurrentPlayerStats.Points),
WinsText(CurrentPlayerStats.Wins))
StatsBillboard.SetText(PlayerStatsText)
# Aggiorna i billboard delle statistiche ordinandoli in base alla quantità di punti lifetime
# di ogni giocatore.
UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void=
var PlayerAndStatsArray:[]player_and_stats =
for:
Agent:Players
Player := player[Agent]
PlayerStats := GetPlayerStats[Player]
do:
player_and_stats:
Player := Player
StatsTable := PlayerStats
# Confronta e ordina i giocatori in base ai loro punti totali che sono il metro di misura
# del "miglior" giocatore nella lobby. Qui puoi cambiare la funzione di confronto in base alle
# esigenze della tua esperienza.
SortedPlayersAndStats := SortingAlgorithms.MergeSort(
MorePointsComparison,
PlayerAndStatsArray)
for:
PlayerIndex -> PlayerAndStats : SortedPlayersAndStats
StatsBillboard := StatsBillboards[PlayerIndex]
do:
UpdateStatsBillboard(PlayerAndStats.Player, StatsBillboard)
# Aggiorna i dispositivi dei riferimenti dei giocatori ordinandoli in base alla quantità
# di punti lifetime di ogni giocatore.
UpdatePlayerReferences<public>(Players:[]player, PlayerReferences:[]player_reference_device):void=
var PlayerAndStatsArray:[]player_and_stats =
for:
Agent:Players
Player := player[Agent]
PlayerStats := GetPlayerStats[Player]
do:
player_and_stats:
Player := Player
StatsTable := PlayerStats
# Confronta e ordina i giocatori in base ai loro punti totali che sono il metro di misura
# del "miglior" giocatore nella lobby. Qui puoi cambiare la funzione di confronto in base alle
# esigenze della tua esperienza.
SortedPlayersAndStats := SortingAlgorithms.MergeSort(
MorePointsComparison,
PlayerAndStatsArray)
for:
PlayerIndex -> PlayerAndStats : SortedPlayersAndStats
PlayerReference := PlayerReferences[PlayerIndex]
do:
PlayerReference.Register(PlayerAndStats.Player)
player_stats_manager.verse
# Questo file gestisce the codice di inizializzazione, aggiornamento e restituzione di player_stats_tables
# per ogni giocatore. Definisce anche una classe stat_type astratta da usare per l'aggiornamento delle statistiche e il
# modulo StatType da usare quando vengono visualizzate le statistiche.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Restituisci il player_stats_table per l'agente fornito.
GetPlayerStats<public>(Agent:agent)<decides><transacts>:player_stats_table=
var PlayerStats:player_stats_table = player_stats_table{}
if:
Player := player[Agent]
PlayerStatsTable := PlayerStatsMap[Player]
set PlayerStats = MakePlayerStatsTable(PlayerStatsTable)
PlayerStats
# Inizializza le statistiche per tutti i giocatori attuali.
InitializeAllPlayerStats<public>(Players:[]player):void =
for (Player : Players):
InitializePlayerStat(Player)
# Inizializza le statistiche per il giocatore indicato.
InitializePlayerStat<public>(Player:player):void=
if:
not PlayerStatsMap[Player]
set PlayerStatsMap[Player] = player_stats_table{}
else:
Print("Impossibile inizializzare le statistiche del giocatore")
# Aggiunge allo StatToAdd dell'agente dato e aggiorna entrambe le loro tabelle delle statistiche
# in PlayerStatsManager e il billboard nel livello.
AddPoints<public>(Agent:agent, NewPoints:int):void=
if:
Player := player[Agent]
PlayerStatsTable := PlayerStatsMap[Player]
CurrentPoints := PlayerStatsTable.Points
set PlayerStatsMap[Player] = player_stats_table:
MakePlayerStatsTable<constructor>(PlayerStatsTable)
Points := CurrentPoints + NewPoints
else:
Print("Impossibile registrare i punti del giocatore")
# Aggiunge allo StatToAdd dell'agente dato e aggiorna entrambe le loro tabelle delle statistiche
# in PlayerStatsManager e il billboard nel livello.
AddWin<public>(Agent:agent, NewWins:int):void=
if:
Player := player[Agent]
PlayerStatsTable := PlayerStatsMap[Player]
CurrentWins := PlayerStatsTable.Wins
set PlayerStatsMap[Player] = player_stats_table:
MakePlayerStatsTable<constructor>(PlayerStatsTable)
Wins := CurrentWins + NewWins
else:
Print("Impossibile registrare le vittorie del giocatore")
player_leaderboards_example.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { PlayerStatistics }
using { PlayerLeaderboard }
# Visita https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse per maggiori informazioni sulla creazione di un dispositivo Verse.
# Dispositivo di Fortnite Creativo sviluppato con Verse che può essere inserito in un livello
player_leaderboards_example := class(creative_device):
# Rappresentazioni visive di ogni giocatore.
@editable
PlayerReferences:[]player_reference_device = array{}
# Billboard che visualizzano le statistiche di ogni giocatore.
@editable
Leaderboards:[]billboard_device = array{}
# Tiene sotto controllo i momenti in cui i giocatori terminano una gara e assegna la vittoria ai giocatori in prima posizione.
@editable
RaceManager:race_manager_device = race_manager_device{}
# Posizione minima in cui si deve piazzare un giocatore per ottenere una vittoria.
@editable
PlacementRequiredForWin:int = 1
# Numero di punti che i giocatori ottengono in base alla posizione.
# Regolalo per assegnare il punteggio che desideri ai tuoi giocatori
# in base alla loro posizione.
@editable
PointsPerPlace:[]int = array{5, 3, 1}
# Posizione dell'ultimo giocatore che ha completato la gara.
# Ai primi tre giocatori che terminano la gara viene assegnata una vittoria.
var CurrentFinishOrder:int = 0
# Viene eseguito quando il dispositivo viene avviato in un gioco in esecuzione
OnBegin<override>()<suspends>:void=
# Prendi i giocatori nella gara attuale e crea una player_stat_table
# per ognuno di loro.
Players := GetPlayspace().GetPlayers()
InitializeAllPlayerStats(Players)
UpdateStatsBillboards(Players, Leaderboards)
UpdatePlayerReferences(Players, PlayerReferences)
# Attendi che tutti i giocatori terminino la gara.
for:
Player:Players
do:
spawn{WaitForPlayerToFinishRace(Player)}
# Quando un giocatore termina la gara, registra un fine gara nella sua tabella delle statistiche.
WaitForPlayerToFinishRace(Player:agent)<suspends>:void=
race:
# Attendi che questo giocatore termini la gara e poi registra il fine gara.
loop:
FinishingPlayer := RaceManager.RaceCompletedEvent.Await()
if:
FinishingPlayer = Player
then:
RecordPlayerFinish(Player)
break
# Attendi che questo giocatore esca dal gioco.
loop:
LeavingPlayer := GetPlayspace().PlayerRemovedEvent().Await()
if:
LeavingPlayer = Player
then:
break
# Quando un giocatore termina la gara, assegnagli i punti in base alla sua posizione e una vittoria se
# la sua posizione è migliore di PlacementRequiredForWin.
RecordPlayerFinish(Player:agent):void=
PlayerFinishOrder:int = CurrentFinishOrder
set CurrentFinishOrder += 1
if:
PointsToAward := PointsPerPlace[PlayerFinishOrder]
then:
AddPoints(Player, PointsToAward)
# Se la posizione finale di un giocatore è minore o uguale a PlacementRequiredToWin,
# assegnagli una vittoria e registralo nella sua player_stats_table.
if:
PlayerFinishOrder < PlacementRequiredForWin
then:
AddWin(Player, 1)