Nei giochi multiplayer, team di giocatori competono tra loro o collaborano per raggiungere un obiettivo. Il numero di giocatori di un team può influire notevolmente sul gameplay e molti sviluppatori scelgono determinati proporzioni di giocatori per creare esperienze piacevoli.
Il bilanciamento dei team consente di dividere i giocatori in team con una proporzione predefinita. Nella maggior parte dei giochi multigiocatore, i giocatori vengono divisi equamente in modo che nessun team abbia un vantaggio. Alcuni giochi creano invece intenzionalmente scenari sbilanciati, ad esempio mettendo quattro giocatori contro un singolo giocatore molto potente. Indipendentemente dalla configurazione, il bilanciamento dei team è fondamentale per creare esperienze interessanti per i team di giocatori.
In questa guida scoprirai come bilanciare in modo dinamico i team di giocatori durante l'esecuzione del gioco e ogni volta che un nuovo giocatore si unisce al gioco. Lo script completo è incluso come riferimento alla fine di questa guida.
Funzionalità del linguaggio Verse utilizzate
array: questo dispositivo utilizza array per memorizzare un riferimento per ciascun team.
option: questo dispositivo utilizza delle opzioni per determinare se esiste un team con un numero di giocatori inferiore a quello in cui un giocatore si trova attualmente.
for: con l'espressione for, puoi scorrere gli array utilizzati dal dispositivo.
if: l'espressione if viene utilizzata per verificare se i giocatori devono cambiare team in base alle dimensioni dello stesso.
failure: i contesti di errore vengono utilizzati per accedere agli array e per controllare il flusso del programma.
API Verse utilizzate
Sottoscrivibile: ti iscriverai a
PlayerAddedEvent()per ribilanciare dinamicamente le squadre quando un nuovo giocatore si unisce a una partita in corso.Team: la classe team aggiunge, rimuove e preleva giocatori dai team. In questo tutorial, utilizzerai la classe team per manipolare direttamente i giocatori e la loro assegnazione a un team.
Spazio di gioco: Lo spazio di gioco tiene traccia degli eventi a cui i giocatori possono sottoscriversi e che sono legati all'accesso e all'abbandono del gioco. Inoltre, ti permette di recuperare elenchi di giocatori e team e di trovare il team di un determinato giocatore. In questo tutorial, ti sottoscriverai a più eventi di spazio di gioco e identificherai giocatori e team utilizzando i metodi di spazio di gioco per poterli manipolare direttamente.
Configurazione del livello
Questo esempio utilizza il dispositivo seguente:
4 Dispositivo Pedana di generazione giocatore: questo dispositivo definisce la posizione di generazione del giocatore all'inizio del gioco.
Segui questi passaggi per impostare il tuo livello:
Aggiungi una Pedana di generazione giocatore al livello.
Seleziona la pedana di generazione in Outliner per aprire il relativo pannello Dettagli .
Nel pannello Dettagli , sotto Opzioni utente:
Imposta Team giocatore su Indice team con un valore di 1
Abilita Visibile nel gioco
Fai clic sull'immagine per ingrandirla.
Duplica la pedana di generazione e posizionala vicino a quella originale.
Duplica le due pedane di generazione e posizionale lontano dal primo gruppo di pedane di generazione. Nella posizione scelta verranno generati i giocatori del Team 2.
Seleziona le pedane di generazione duplicate e nel pannello Dettagli alla voce Opzioni utente, modifica il valore di Indice team in 2 per entrambe.
Nell'Outliner, seleziona il dispositivo Impostazioni isola per aprire il relativo pannello Dettagli. In Opzioni utente - Regole del gioco:
Imposta Team su Indice team con un valore di 2. In questo esempio vengono utilizzati due team, ma puoi sempre selezionare qualsiasi numero desiderato.
Imposta Dimensione team su Dinamico. Questa impostazione fa sì che il tuo codice Verse abiliti il bilanciamento dei team.
Imposta Partecipazione in corso su Genera in modo che nuovi giocatori possano unirsi alla partita mentre è in corso.
Fai clic sull'immagine per ingrandirla.
Crea un nuovo dispositivo Verse denominato team_multiplayer_balancing utilizzando Verse Explorer e trascina il dispositivo nel livello. (Per informazioni su come creare un nuovo dispositivo in Verse, vedi Creare un dispositivo personalizzato utilizzando Verse.)
Il livello deve essere simile a questa configurazione:
Distribuzione equa dei team
Bilanciamento dei team all'inizio del gioco
In questo passaggio ti spiegheremo come dividere i giocatori in team bilanciati all'inizio del gioco e tutte le volte che si aggiunge un nuovo giocatore.
Apri Verse Explorer e fai due volte clic su team_multiplayer_balancing.verse per aprire lo script in Visual Studio Code.
Nella definizione della classe
team_multiplayer_balancing,aggiungi un arrayteamvariabile denominatoTeamsche memorizzerà i riferimenti a ogni team in cui i giocatori si trovano.Verseteam_multiplayer_balance := class(creative_device): # Holds the teams found with GetTeams() var Teams : []team = array{}Nella funzione
OnBegin()aggiorna l'arrayTeamsin modo che corrisponda ai team impostati in precedenza in Impostazioni isola. Chiama la funzioneGetTeams()dall'APIfort_team_collectionper ottenere tutti i team nello spazio di gioco.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()Trova tutti i giocatori del gioco chiamando la funzione
GetPlayers()e salvali in un array di giocatori chiamatoAllPlayers.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() AllPlayers := GetPlayspace().GetPlayers()Scorri l'elenco dei giocatori e crea team con lo stesso numero di giocatori. Dovrai confrontare il team di appartenenza attuale di un giocatore con qualsiasi altro team e stabilire se è il più adatto a quel giocatore. In questo caso, puoi utilizzare il team a cui un giocatore viene assegnato automaticamente all'inizio del gioco utilizzando
GetTeam[](poiché i giocatori devono far parte di un team nelle modalità di gioco a più team). Tieni presente cheGetTeam[]richiede un parametro di tipo agente, ma dato che il giocatore è una sottoclasse di agente, puoi passare un giocatore senza type casting.VerseAllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalancedDato che team è una classe interna, può essere inizializzata e utilizzata solo come riferimento a un oggetto team esistente.
Vuoi assegnare i giocatori al team con il minor numero di giocatori fino a quando tutti i team non saranno bilanciati. Per farlo, devi controllare ogni giocatore e ogni team utilizzando un
forloop. Sebbene potresti utilizzare anche due loop `for`, uno per passare in rassegna i giocatori e uno per passare in rassegna i team, in questo esempio estrarrai il loop for del team in un metodo a sé stante. Imposta il giocatore per il loop ottenendo un riferimento a tutti i giocatori e poi un riferimento a ogni team in cui si trovano in una costante chiamataCurrentTeam.Crea uno nuovo intero variabile
TeamSizee inizializzalo su0, quindi impostala uguale alle dimensioni del team in cui il giocatore si trova attualmente. PoichéGetAgents[]è un'espressione fallibile, devi includere questo set in un'istruzione if.Versefor (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalanced var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")Crea un metodo denominato
FindSmallestTeam(). Questo metodo restituisce un team opzionale (?team) quandoTeamSizeviene passato come argomento e si occuperà di trovare e restituire il team con il minor numero di giocatori. Inizializza una nuova opzione di team chiamataSmallestTeaminFindSmallestTeam(). Utilizzerai un'opzione qui perché un giocatore potrebbe già far parte del team meno numeroso quando chiamiFindSmallestTeam().Poiché l'opzione
SmallestTeamè impostata su falso per impostazione predefinita, rimanefalsose non viene trovato un team più piccolo. SeFindSmallestTeam()restituiscefalse, saprai con certezza che il giocatore in questione era già membro del team più piccolo. Devi inizializzare anche una variabile intCurrentTeamSizecon il valoreTeamSize. La variabileCurrentTeamSizedeve essere impostata per essere aggiornata in base alle dimensioni di qualsiasi altro team con meno giocatori.VerseFindSmallestTeam(CurrentTeamSize : int) : ?team= var SmallestTeam : ?team = false var TeamSize : int = CurrentTeamSizePoiché
TeamSizetiene traccia delle dimensioni diSmallestTeam, devi confrontarla con le dimensioni di ogni team. Scorri ogni team e ottieni le relative dimensioni in forma di un numero intero localeCandidateTeamSize. SeCandidateTeamSizeè inferiore aTeamSize, impostaSmallestTeamsu questo team eTeamSizesulle sue relative dimensioni.La condizione
TeamSize > CandidateTeamSizeè una condizione di filtro perché è controllata tra parentesi del loop for. L'utilizzo di una condizione di filtro assicura che il codice all'interno del loop venga eseguito solo se la condizione è soddisfatta. Ciò garantisce cheSmallestTeamsia impostato sul team con il minor numero di giocatori, se ne viene trovato uno. Se non viene trovato alcun team con meno giocatori,SmallestTeamrimarrà impostato su falso.Infine, restituisce
SmallestTeamquando tutti i team sono stati controllati.Versefor(Team : Teams, CandidateTeamSize := GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize): set SmallestTeam = option{Team} set TeamSize = CandidateTeamSize Print("Found a team with less players: {CandidateTeamSize}") return SmallestTeamIn
OnBegin(), crea una nuova opzione team denominataSmallestTeamall'interno del loopfore inizializzala al valore diFindSmallestTeam()quando viene passatoTeamSizecome argomento.VerseSmallestTeam : ?team = FindSmallestTeam(TeamSize)Quindi, prova ad accedere al valore nella variabile opzionale
SmallestTeam. Se il valore è impostato su falso, significa che il giocatore faceva già parte del team più piccolo e che non è necessario assegnarlo. In caso contrario, dovrai assegnare il giocatore al suo nuovo team. Dal momento che molti metodi non permettono di passare un'opzione direttamente come argomento, dovrai estrarre il valore in una variabile localeTeamToAssign. Puoi provare ad assegnare un giocatore a questo team utilizzandoAddToTeam[player, team]. Tieni presente che l'assegnazione non riesce sempre se si cerca di associare un giocatore al suo team di appartenenza attuale. Tuttavia, ciò non ha alcun effetto negativo, poiché il loopforpassa semplicemente al giocatore successivo e lascia il primo giocatore nel suo team originale.Verseif (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")
OnBegin()deve essere simile al blocco di codice seguente.VerseOnBegin<override>()<suspends> : void = Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() Print("Beginning to Assign Players") Playspace := GetPlayspace() AllPlayers := Playspace.GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := Playspace.GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = Playspace.GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")
Gestione di un giocatore che si unisce a metà gioco
Se desideri rendere i team bilanciati anche durante il corso di un gioco, dovrai sottoscrivere l'evento che si attiva ogni volta che un nuovo giocatore si unisce al team. Per non dover ripetere tutto il codice che hai appena scritto, potrai convertirlo in un metodo comune.
Crea un metodo denominato
BalanceTeams()e sposta tutto il codice dopo aver impostato la variabileTeamsutilizzandoGetTeams(). Questo metodo viene richiamato nel metodoOnBegin()per bilanciare i team all'inizio del gioco.BalanceTeams()dovrebbe essere simile al seguente.VerseBalanceTeams() : void = AllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}") SmallestTeam : ?team = FindSmallestTeam(TeamSize) if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")Crea un altro metodo chiamato
OnPlayerAdded()che contiene una chiamata aBalanceTeams(). Anche se la variabileplayernon viene utilizzata, la definizione del metodo la richiede perché ti iscrivi aPlayerAddedEvent()utilizzando questo metodo. Per maggiori dettagli sugli eventi a cui è possibile sottoscriversi, vedi la pagina Codifica delle interazioni con i dispositivi.VerseOnPlayerAdded(InPlayer : player) : void = Print("A new Player joined, assigning them to a team!") BalanceTeams()In
OnBegin(), sottoscriviPlayerAddedEvent()utilizzandoOnPlayerAdded. Ora, quando un nuovo giocatore si unirà al gioco,OnPlayerAddedchiameràBalanceTeams()per bilanciare automaticamente i team.VerseOnBegin<override>()<suspends> : void = GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) Print("Beginning to balance teams") BalanceTeams()Salva lo script in Visual Studio Code e fai clic su Compila il codice Verse per compilare il tuo script.
Fai clic su Avvia sessione nella barra degli strumenti UEFN per eseguire il playtest del livello.
Durante il playtest del livello, devi visualizzare le dimensioni di ogni team e i team più piccoli trovati dallo script registrati nel registro di output. I giocatori devono essere distribuiti in modo uniforme tra i team e ogni nuovo partecipante deve essere aggiunto per mantenere questo equilibrio.
Script completo
Il codice seguente è lo script completo per un dispositivo che fa sì che i team di giocatori vengano sempre automaticamente bilanciati.
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
team_multiplayer_balance := class(creative_device):
# Holds the teams found with GetTeams()
var Teams : []team = array{}
OnBegin<override>()<suspends> : void =
Print("Verse Device Started!")
In autonomia
In questo tutorial, hai imparato come creare con Verse un dispositivo che bilancia i team di giocatori.
Sfrutta ora le conoscenze acquisite per creare team deliberatamente sbilanciati per modalità di gioco asimmetriche, come un giocatore uno contro quattro.