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
] (array-in-verse): questo dispositivo utilizza array per memorizzare un riferimento per ciascun team. -
option
: questo dispositivo utilizza opzioni per determinare se esiste un team con meno giocatori del team in cui si trova attualmente un giocatore. -
for
: con l'espressionefor
, è possibile iterare l'array utilizzato dal dispositivo. -
if
: l'espressioneif
viene utilizzata per verificare se i giocatori devono cambiare team in base alle dimensioni dello stesso. -
failure
: i contesti di errore sono utilizzati per accedere agli array e per controllare il flusso del programma.
API Verse utilizzate
-
Sottoscrizione possibile: puoi sottoscrivere
PlayerAddedEvent()
per riequilibrare in modo dinamico i team quando un nuovo giocatore si unisce a una gioco 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 alla partecipazione e all'abbandono di una 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 diversi eventi di spazio di gioco e identificherai giocatori e team utilizzando i metodi di spazio di gioco per poterli manipolare direttamente.
Configurazione di un livello
Questo esempio utilizza il dispositivo seguente:
4 pedane 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.
-
In Outliner, seleziona il dispositivo Impostazioni isola per aprire il relativo pannello Dettagli. Nella sezioneOpzioni 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 Dimensioni team su Dinamico. Questa impostazione fa sì che il tuo codice Verse abiliti il bilanciamento dei team.
-
Imposta Partecipazione in corso su Generazione in modo che nuovi giocatori possano unirsi a un gioco in corso.
Fai clic sull'immagine per ingrandirla.
-
-
Crea un nuovo dispositivo Verse denominato team_multiplayer_balancing utilizzando Verse Explorer e trascinalo 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 giocatori nei 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 array variabile denominatoTeams
che memorizzerà i riferimenti di ciascun team a cui appartengono i giocatori.team_multiplayer_balance := class(creative_device): # Mantiene i team trovati con GetTeams() var Teams : []team = array{}
-
Nella funzione
OnBegin()
, aggiorna l'arrayTeam
in modo che corrisponda all'impostazione team descritta in precedenza in Impostazioni isola. Puoi usare la funzione di chiamataGetTeams()
dell'APIfort_team_collection
API per avere tutti i team nello spazio di gioco.OnBegin<override>()<suspends>:void= Print("Dispositivo Verse avviato!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()
-
Trova tutti i giocatori nel gioco chiamando la funzione
GetPlayers()
e salvali in un array di giocatori denominatoAllPlayers
.OnBegin<override>()<suspends>:void= Print("Dispositivo Verse avviato!") 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 per 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 la necessità di un cast di tipo.AllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assegna i giocatori a un nuovo team se i team esistenti sono poco bilanciati
Dato 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 loop
for
. Sebbene potresti utilizzare anche due loopfor
, 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 una nuova variabile intera
TeamSize
e inizializzala a0
, 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.for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assegna i giocatori a un nuovo team se i team esistenti sono poco bilanciati var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("La dimensione del team iniziale del giocatore è {TeamSize}")
- Crea un metodo chiamato
FindSmallestTeam()
. Questo metodo restituisce un team opzionale (?team
) quandoTeamSize
viene passato come argomento e si occupa di trovare e restituire il team con il minor numero di giocatori. Inizializza un nuovo team option denominatoSmallestTeam
all'interno diFindSmallestTeam()
. In questo caso utilizzerai un'opzione, poiché è possibile che un giocatore sia già nel team meno numeroso quandoFindSmallestTeam()
viene chiamata. -
Poiché l'opzione
SmallestTeam
è impostata su falso per impostazione predefinita, rimane tale se 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 intCurrentTeamSize
con il valoreTeamSize
. La variabileCurrentTeamSize
deve essere impostata per essere aggiornata in base alle dimensioni di qualsiasi altro team con meno giocatori.FindSmallestTeam(CurrentTeamSize : int) : ?team= var SmallestTeam : ?team = false var TeamSize : int = CurrentTeamSize
-
Poiché
TeamSize
tiene traccia della dimensione diSmallestTeam
, devi confrontarla con la dimensione di ogni team. Scorri ogni team e ottieni le relative dimensioni in forma di un numero intero localeCandidateTeamSize
. SeCandidateTeamSize
è inferiore aTeamSize
, impostaSmallestTeam
su questo team eTeamSize
sulle sue relative dimensioni.La condizione
TeamSize > CandidateTeamSize
è una condizione di filtro, perché viene controllata tra le parentesi nel loop for. L'utilizzo di una condizione di filtro assicura che il codice all'interno del loop venga eseguito solo se la condizione è soddisfatta. Questo assicura cheSmallestTeam
sia impostato sul team con il minor numero di giocatori se viene trovato un team. Se invece non viene trovato alcun team con meno giocatori,SmallestTeam
rimane impostato su falso.Infine, restituisce
SmallestTeam
quando tutti i team sono stati controllati.for(Team : Teams, CandidateTeamSize := GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize): set SmallestTeam = option{Team} set TeamSize = CandidateTeamSize Print("Trovato un team con meno giocatori: {CandidateTeamSize}") return SmallestTeam
-
In
OnBegin()
, crea una nuova opzione team chiamataSmallestTeam
all'interno del loopfor
loop e inizializzala al valore diFindSmallestTeam()
quandoTeamSize
viene passato come argomento.SmallestTeam : ?team = FindSmallestTeam(TeamSize)
-
Successivamente, cerca di accedere al valore della 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 loop for passa semplicemente al giocatore successivo e lascia il primo giocatore nel suo team originale.if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Tentativo di assegnare il giocatore a un nuovo team")
-
-
OnBegin()
deve essere simile al blocco di codice seguente.OnBegin<override>()<suspends> : void = Print("Dispositivo Verse avviato!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() Print("Avvio dell'assegnazione dei giocatori") 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("La dimensione del team iniziale del giocatore è {TeamSize}") SmallestTeam : ?team = FindSmallestTeam(TeamSize) if (TeamToAssign := SmallestTeam?, Playspace.GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Tentativo di assegnare il giocatore a un nuovo team")
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 chiamato
BalanceTeams()
e sposta tutto il codice lì dopo aver definito la variabileTeams
utilizzandoGetTeams()
. Questo metodo viene richiamato nel metodoOnBegin()
per bilanciare i team all'inizio del gioco. Il metodoBalanceTeams()
deve essere simile al codice seguente:BalanceTeams() : 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("La dimensione del team iniziale del giocatore è {TeamSize}") SmallestTeam : ?team = FindSmallestTeam(TeamSize) if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Tentativo di assegnare il giocatore a un nuovo team")
-
Crea un altro metodo chiamato
OnPlayerAdded()
che contiene una chiamata aBalanceTeams()
. Anche se la variabileplayer
non viene utilizzata nel corpo del metodo, la dovrai comunque definire come parametro del metodo perché viene sottoscritto l'eventoPlayerAddedEvent()
. Per maggiori dettagli sugli eventi a cui è possibile sottoscriversi, vedi Codifica delle interazioni con i dispositivi.OnPlayerAdded(InPlayer : player) : void = Print("Si è unito un nuovo giocatore, assegnazione a un team in corso!") BalanceTeams()
-
In
OnBegin()
, sottoscrivi l'eventoPlayerAddedEvent()
utilizzandoOnPlayerAdded
. D'ora in avanti, quando un nuovo giocatore si unirà al gioco,OnPlayerAdded
chiameràBalanceTeams()
per bilanciare automaticamente i team.OnBegin<override>()<suspends> : void = GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) Print("Avvio del bilanciamento dei team") BalanceTeams()
-
Salva lo script in Visual Studio Code e fai clic su Compila script 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):
# Mantiene i team trovati con GetTeams()
var Teams : []team = array{}
OnBegin<override>()<suspends> : void =
Print("Dispositivo Verse avviato!")
set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()
AllPlayers := GetPlayspace().GetPlayers()
#Sottoscrive l'evento PlayerAddedEvent per consentire il ribilanciamento del team quando un nuovo giocatore si unisce al gioco
Self.GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
Print("Avvio del bilanciamento dei team")
BalanceTeams()
#Gestisce un nuovo giocatore che partecipa al gioco
OnPlayerAdded(InPlayer : player) : void =
Print("Si è unito un nuovo giocatore, assegnazione a un team in corso!")
BalanceTeams()
<#
Per ogni giocatore, trova il numero di giocatori del team a cui appartiene. Scorri
l'elenco dei team e assegna i giocatori al team con il minor numero di giocatori o
crea un nuovo team in caso di parità.
#>
BalanceTeams() : void =
AllPlayers := GetPlayspace().GetPlayers()
for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]):
# Assegna i giocatori a un nuovo team se i team esistenti sono poco bilanciati
var TeamSize:int = 0
if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length):
Print("La dimensione del team iniziale del giocatore è {TeamSize}")
SmallestTeam : ?team = FindSmallestTeam(TeamSize)
if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]):
Print("Tentativo di assegnare il giocatore a un nuovo team")
FindSmallestTeam(CurrentTeamSize : int) : ?team =
var SmallestTeam : ?team = false
var TeamSize : int = CurrentTeamSize
<#
Ottiene il numero di giocatori di ogni team. Se un team ha numero di giocatori minore rispetto a SmallestTeam,
imposta SmallestTeam a Team e aggiorna TeamSize al numero di giocatori del nuovo team
#>
for(Team : Teams, CandidateTeamSize := GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize):
set SmallestTeam = option{Team}
set TeamSize = CandidateTeamSize
Print("Trovato un team con meno giocatori: {CandidateTeamSize}")
return SmallestTeam
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.