Nei giochi di corse, è comune che i giocatori abbiano una posizione di partenza diversa in base a quanto bene si sono comportati in un round precedente. Incoraggia i giocatori a finire la gara velocemente anche quando non sono al primo posto, quindi partono prima degli altri giocatori.
Per raggiungere questo obiettivo, il gioco deve sapere in quale round si trovano attualmente i giocatori e l'ordine di arrivo del pilota deve persistere in tutti i round, ma non in tutte le sessioni di gioco. Una variabile di mappa debole della sessione in Verse reimposta i dati a ogni round, quindi queste informazioni sul round devono essere memorizzate con ogni giocatore utilizzando una variabile di mappa debole del giocatore e reimpostate dopo la fine del gioco.
Attualmente, un progetto può avere solo fino a due variabili di mappa deboli del giocatore. Se il tuo progetto ha già una variabile di mappa debole del giocatore, è una buona idea fare in modo che la seconda registri le informazioni del round per differenziare i dati che devono sempre persistere dai dati che reimposterai dopo la fine del gioco o dopo che un giocatore ha lasciato la sessione.
È anche importante sapere in quale round si trovano attualmente i giocatori per applicare la logica specifica del round e reimpostare le informazioni sul round dell'ultimo round. Al momento non esiste un'API per ottenere il round attuale, quindi queste informazioni devono essere registrate anche nei dati persistenti per ogni giocatore.
In sintesi, avrai bisogno di una variabile di mappa debole del giocatore che abbia almeno le seguenti informazioni:
Termina l'ordine
Ultimo round completato
Le sezioni seguenti illustrano come impostare questi dati e la logica di round. Puoi trovare il codice completo alla fine della pagina.
Registra l'ultimo round completato
Segui questa procedura per impostare i dati persistenti per ogni giocatore e registrare l'ultimo round completato.
Crea una classe persistente denominata
player_circuit_infoper memorizzare le informazioni sui giocatori nei round. Questa classe deve avere i campi per rappresentare l'ultimo ordine di arrivo del giocatore,LastRoundFinishOrder, e il suo ultimo round completato,LastCompletedRound. Questi campi vengono inizializzati con-1per rappresentare valori non validi in modo da sapere quando questi campi contengono effettivamente informazioni utili.Verse# Tracks the number of and in what order a player finished the previous round. player_circuit_info<public> := class<final><persistable>: Version:int = 0 LastRoundFinishOrder:int = -1 LastCompletedRound<public>:int = -1Crea una variabile di mappa debole del giocatore utilizzando la classe
player_circuit_infoper mantenere le informazioni sul round con i giocatori.Verse# A persistable map that maps each player to # what order they finished the previous round. var CircuitInfo<public>:weak_map(player, player_circuit_info) = map{}Come procedura consigliata per l'uso di dati persistenti, crea un costruttore per la classe persistente in modo che sia in grado di aggiornare facilmente le informazioni per ogni giocatore. Per maggiori dettagli, consulta utilizzo dei costruttori per gli aggiornamenti parziali.
Verse# Creates a new player_circuit_info from the given older player_circuit_info. MakePlayerCircuitInfo<constructor>(OldPlayerCircuitInfo:player_circuit_info)<transacts> := player_circuit_info: Version := OldPlayerCircuitInfo.Version LastRoundFinishOrder := OldPlayerCircuitInfo.LastRoundFinishOrder LastCompletedRound := OldPlayerCircuitInfo.LastCompletedRoundOra che hai definito le strutture per questi dati, aggiungi una funzione per registrare l'ordine di arrivo di un giocatore e aggiornare i dati persistenti. Questa funzione utilizza il costruttore realizzato nel passaggio precedente per aggiornare parzialmente i dati per l'unica informazione che ti interessa: l'ordine di arrivo.
Verse# Creates a new player_circuit_info for the given player with the order they finished the round in. RecordPlayerFinishOrder<public>(Agent:agent, FinishOrder:int)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo:player_circuit_info = if: Info := CircuitInfo[Player] then: Info else: player_circuit_info{}Crea un'altra funzione per aggiornare solo l'ultimo round completato del giocatore.
Verse# Updates a player's player_circuit_info with their last completed round. UpdateRound<public>(Agent:agent, CompletedRound:int)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] set CircuitInfo[Player] = player_circuit_info: MakePlayerCircuitInfo<constructor>(PlayerCircuitInfo) LastCompletedRound := CompletedRoundOra che puoi registrare l'ultimo round completato del giocatore, crea una funzione per calcolare l'ultimo round completato del gioco controllando quali giocatori hanno l'ultimo round registrato. Devi controllare tutti i giocatori per tenere conto dei giocatori che potrebbero essersi uniti alla sessione in corso. L'ultima variabile di round completato viene inizializzata con
-1per rappresentare i dati non validi. Se un giocatore ha un valore maggiore di-1, il round è già terminato.Verse# Returns the highest last completed round among all players. GetLastCompletedRound<public>(Players:[]player, TotalRounds:int)<transacts>:int= var LastCompletedRound:int = -1 for: Player : Players Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] do: # Update LastCompletedRound if this player has the highest last completed round. else if:Crea un dispositivo Verse per verificare che l'ordine di arrivo del round e del giocatore funzioni come previsto. Assicurati che il tuo progetto sia impostato per più round, impostando la proprietà Round totali in Impostazioni isola.
Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= Players := GetPlayspace().GetPlayers() CurrentRound := GetLastCompletedRound(Players) + 1 Print("Current round is {CurrentRound}") for:
Reimposta le informazioni sul round quando il giocatore lascia
I dati persistenti del giocatore per le informazioni sul round devono essere reimpostati quando un giocatore esce durante la partita. Puoi iscriverti all'evento PlayerRemovedEvent dello spazio di gioco per sapere quando se ne va.
Segui questa procedura per reimpostare le informazioni del round quando un giocatore se ne va:
Crea una funzione per reimpostare i dati persistenti del giocatore per le informazioni sul round. Ciò significa impostare i valori su
-1o qualsiasi cosa tu decida per rappresentare i dati non validi di quei campi. Questa implementazione consente di scegliere quali dati devono essere reimpostati nel caso in cui si aggiungano altre informazioni in un secondo momento alla classe persistente che non devono essere reimpostate qui.Verse# Resets a player's player_circuit_info. ResetCircuitInfo<public>(Agent:agent)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] set CircuitInfo[Player] = player_circuit_info: MakePlayerCircuitInfo<constructor>(PlayerCircuitInfo) LastRoundFinishOrder := -1 LastCompletedRound := -1Crea una funzione denominata
OnPlayerRemovedper reimpostare le informazioni sul round quando un giocatore se ne va.Verse# When a player is removed from the race, reset their circuit to prevent their # stats from showing up on billboards and player references. OnPlayerRemoved(Player:player):void= # Reset circuit info when player leaves the game. if: ResetCircuitInfo[Player] else: Print("Unable to reset circuit info for player")Imposta la funzione
OnPlayerRemovedda chiamare quando un giocatore lascia il gioco, sottoscrivendo l'eventoGetPlayspace().PlayerRemovedEvent().Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved) Players := GetPlayspace().GetPlayers() CurrentRound := GetLastCompletedRound(Players) + 1Prova per verificare che un giocatore che esce dal gioco reimposti le proprie informazioni.
Reimposta le informazioni sul round alla fine del gioco
La funzione OnBegin di un dispositivo Verse viene eseguita all'inizio di ogni round. Questo è un buon momento per determinare se un giocatore dispone di dati persistenti imprevisti, ad esempio se l'ultimo round completato è uguale al numero totale di round. In tal caso, devi reimpostare i dati del giocatore. Al momento non esiste un'API per conoscere il numero totale di round in un gioco. Invece, dovrai aggiungere una proprietà modificabile al dispositivo Verse per i round totali nel codice Verse e assicurarti che corrisponda alla proprietà Round totali in Impostazioni isola.
Segui questa procedure per reimpostare le informazioni del round al termine del gioco:
Aggiungi una proprietà modificabile al tuo dispositivo Verse per il numero totale di round nel gioco. TotalRounds non deve essere minore o uguale a
0, quindi vincola i valori della proprietà a un valore maggiore o uguale a1.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)Aggiorna la funzione di
GetLastCompletedRoundper reimpostare i dati persistenti del giocatore dell'ultimo round completato se è superiore al numero previsto di round nel gioco.Verse# Returns the highest last completed round among all players. GetLastCompletedRound<public>(Players:[]player, TotalRounds:int)<transacts>:int= var LastCompletedRound:int = -1 for: Player : Players Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] do: # If player's recorded info is greater than the total rounds for whatever reason, # then need to reset the player's circuit info because they shouldn't have more than what's allowed.Aggiorna la chiamata a
GetLastCompletedRoundper passare i round totali come argomento per reimpostare le informazioni sul round del giocatore se si trova in uno stato imprevisto.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)Prova per verificare che le informazioni sul round del giocatore si azzerano anche dopo aver giocato e completato tutti i round.
Aggiunta di logica basata sul round corrente
Ora, puoi utilizzare queste informazioni per avere una logica personalizzata a seconda del round in cui si trovano i giocatori. Ad esempio, potresti mostrare una classifica locale per il primo round di una partita.
Chiamare GetLastCompletedRound() ogni volta che hai bisogno di sapere quale round si sta giocando non è l'ideale. Invece, puoi farlo una volta per round e registrare le informazioni sul round in una variabile di mappa debole della sessione in modo che tutto il codice Verse nel progetto possa accedere a questo valore in qualsiasi momento senza doverlo ricalcolare ogni volta.
Questo è un ottimo esempio per mostrare le differenze e il ragionamento per l'utilizzo della variabile della mappa debole della sessione e della variabile della mappa debole del giocatore nel codice:
Le variabili di mappa deboli della sessione sono utili per i singleton e per l'archiviazione dei dati del round corrente che non si desidera ricalcolare ogni volta.
Le variabili di mappa debole del giocatore sono progettate per le informazioni che devono persistere in più round e sessioni di gioco, ma devono essere associate ai singoli giocatori.
Segui questa procedura per impostare una variabile di mappa debole della sessione per la memorizzazione del round attuale.
Crea una classe per memorizzare le informazioni sul round. Hai almeno bisogno di un campo per
CurrentRound, ma potresti includere altre informazioni sul round che desideri salvare in tutto il tuo codice Verse, come ad esempio le posizioni di partenza e i veicoli dei giocatori. InizializzaCurrentRoundsu-1per rappresentare i dati non validi.Verseround_info := class: CurrentRound:int = -1Crea una variabile di mappa debole della sessione utilizzando la classe
round_infoper memorizzare le informazioni sul round con la sessione.Verse# Maps the current session to its associated round info. var RoundInfo:weak_map(session, round_info) = map{}Aggiungi una funzione getter per ottenere il round corrente dalla variabile di mappa debole della sessione.
VerseGetRound<public>()<decides><transacts>:int= RoundInfo[GetSession()].CurrentRoundAggiungi una funzione per ottenere il round corrente e memorizzarlo nella variabile di mappa debole di sessione.
VerseRecordCurrentRound<public>(Players:[]player, TotalRounds:int):void= var CurrentRoundInfo:round_info = if: Info := RoundInfo[GetSession()] then: Info else: LastCompletedRound := GetLastCompletedRound(Players, TotalRounds) round_info: CurrentRound := LastCompletedRound + 1Aggiorna il tuo dispositivo Verse per utilizzare la nuova funzione
RecordCurrentRounde chiamaGetRoundquando hai bisogno di sapere di quale round si tratta.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)
Ora che queste informazioni sono memorizzate in una variabile di mappa debole della sessione, puoi aggiungere facilmente una logica personalizzata per i round. Ad esempio, puoi verificare se è il primo round e impostare una lobby e un'area di visualizzazione della classifica dei giocatori.
# Returns true if this is the first round of the game.
IsFirstRound<public>(RoundToCheck:int)<decides><transacts>:void=
RoundToCheck <= 0In autonomia
Dai un'occhiata a Gara a circuito con persistenza in Verse per sapere come utilizzare questo codice in un gioco di corse per determinare l'ordine di partenza dei giocatori.
Dopo aver estratto il modello, prova a eseguire le operazioni seguenti:
Aggiungi ulteriori informazioni sul round, ad esempio quale veicolo è assegnato al giocatore.
Teletrasporta i giocatori in diverse aree della mappa all'inizio di ogni round.
Quali altri giochi ti vengono in mente che utilizzano una logica specifica per i round?
Codice completo
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# A persistable map that maps each player to
# what order they finished the previous round.
var CircuitInfo<public>:weak_map(player, player_circuit_info) = map{}
# Maps the current session to its associated round info.
var RoundInfo:weak_map(session, round_info) = map{}