Aggiungere turni

*Questo contenuto è tradotto usando AI (Beta) e potrebbe contenere errori. Per visualizzare questa pagina in inglese, clicca qui.

Aggiungere turni consente di strutturare il gameplay in fasi con un chiaro punto di inizio e di fine, in modo che i giocatori possano misurare i loro progressi e avere un'opportunità periodica per un campo di gioco equo. Questo è particolarmente importante per il gameplay basato su squadre, poiché offre ai giocatori la possibilità di cambiare il proprio stile di gioco a seconda di chi è nella loro squadra durante quel turno.

Utilizzando il gioco di laser tag di esempio come riferimento, questa sezione del tutorial ti insegna come utilizzare e personalizzare le funzionalità integrate di Roblox per strutturare ogni turno, inclusa la guida alla programmazione su:

  • Iniziare un turno resettando i punti individuali e di squadra, quindi facendo spawnare i giocatori nelle loro zone di spawn di squadra.
  • Personalizzare le variabili che impostano l'obiettivo per il turno nella parte superiore dello schermo di ogni giocatore.
  • Monitorare i contributi di punti dei giocatori per il punteggio della loro squadra.
  • Attivare schermate UI uniche a seconda che la squadra del giocatore abbia vinto o perso il turno.
  • Terminare un turno disconnettendo i giocatori e facendoli spawnare nel lobby neutrale.

Dopo aver completato questa sezione, imparerai come implementare un comportamento dei blaster che sia sia preciso che soddisfacente per i giocatori.

Inizio ciclo

ServerScriptServiceGameplayRounds gestisce la maggior parte della logica per implementare i turni e inizia chiamando la funzione startRoundLoopAsync() per segnare l'inizio di un ciclo di turni. Mentre i giocatori si uniscono al lobby e aspettano di essere suddivisi in una squadra, startRoundLoopAsync() chiama la funzione resetScores() in ServerScriptServiceGameplayScoring per resettare sia la classifica che i punti di squadra.

Scoring
function Scoring.resetScores()
for _, player in Players:GetPlayers() do
player.leaderstats.Points.Value = 0
end
for _, team in Teams:GetTeams() do
team:SetAttribute(GuiAttribute.teamPoints, 0)
end
end

Ora che tutti partono da zero punti, startRoundLoopAsync() imposta la proprietà Neutral della posizione di spawn Neutra su false, in modo che solo i giocatori con la stessa proprietà Team.Color della proprietà TeamColor della posizione di spawn possano spawnare lì. Poiché la proprietà TeamColor della posizione di spawn è impostata su bianco invece che sui team di menta o rosa carne dell'esempio, questa configurazione impedisce a tutti i giocatori di spawnare o ri-spawnare lì mentre un turno è attivo.

Per i giocatori che sono attualmente nel lobby, startRoundLoopAsync() passa tutti i giocatori attualmente nel gioco alla funzione spawnPlayersInMap in ServerScriptServiceGameplayRoundsspawnPlayersInMap per suddividere e bilanciare tutti in una squadra con un numero approssimativo di giocatori.

Per i nuovi giocatori che si uniscono al gioco dopo che il gruppo del lobby è stato suddiviso in una squadra, startRoundLoopAsync() ascolta l'evento Players.PlayerAdded:Connect, quindi chiama di nuovo la funzione spawnPlayersInMap per aggiungerli alla squadra con il minor numero di giocatori. Per ulteriori informazioni su questo processo, vedere Configura le posizioni di spawn dalla precedente sezione Spawn e Ri-spawn del tutorial.

Rounds
-- Spawn di tutti i giocatori nella mappa
neutralSpawn.Neutral = false
spawnPlayersInMap(Players:GetPlayers())
-- Spawn di nuovi giocatori nella mappa quando si uniscono
local playerAddedConnection = Players.PlayerAdded:Connect(function(player: Player)
spawnPlayersInMap({ player })
end)

Imposta obiettivo

Ora che ogni giocatore è nell'arena con i propri compagni di squadra, il gioco deve fornire istruzioni su cosa fare per avere successo all'interno del turno. Il gioco di laser tag di esempio affronta questo requisito fornendo un messaggio di obiettivo nella parte superiore dello schermo di ogni giocatore con chiare indicazioni su cosa deve fare la squadra per vincere.

Sebbene tu possa saperne di più su come configurare e visualizzare il componente UI Obiettivo nel Curriculum UI, questa sezione si concentra su come implementare l'obiettivo all'inizio del turno, partendo da come impostare la quantità di punti che ogni squadra deve completare per il turno.

Anche se il messaggio di obiettivo durante l'esecuzione informa i giocatori che devono segnare tre punti per vincere, se esamini il messaggio in StarterGuiHUDGui, puoi vedere che contiene invece una configurazione "%d" per il valore dei punti.

"%d" è una stringa segnaposto che puoi aumentare o diminuire in qualsiasi momento per soddisfare i tuoi requisiti di gioco aggiornando la variabile TEAM_SCORE_LIMIT in ReplicatedStorageTEAM_SCORE_LIMIT. Ad esempio, se impostassi questo numero su un eccessivamente alto 200, il messaggio e il contatore dei punti di squadra si aggiornerebbero di conseguenza.

TEAM_SCORE_LIMIT
local TEAM_SCORE_LIMIT = 200 -- riga aggiornata, assicurati di cambiarla di nuovo
return TEAM_SCORE_LIMIT

Questo semplice aggiornamento della variabile funziona durante l'esecuzione perché, all'inizio del turno, ReplicatedStorageHUDGuiSetupSetObjective richiede lo script del modulo TEAM_SCORE_LIMIT in modo da poter sostituire la stringa segnaposto nell'oggetto TextLabel dell'UI Obiettivo.

TEAM_SCORE_LIMIT
local TEAM_SCORE_LIMIT = require(ReplicatedStorage.TEAM_SCORE_LIMIT)
local function setObjective(gui: ScreenGui)
local bodyTextLabel = gui.Objective.ObjectiveDisplay.Body.BodyTextLabel
bodyTextLabel.Text = bodyTextLabel.Text:format(TEAM_SCORE_LIMIT)
end

Monitora punti

Ora che i giocatori hanno un obiettivo per il turno, il gioco deve tenere traccia dei punti di ogni squadra fino a quando non raggiungono il loro obiettivo. Sebbene il comportamento predefinito del servizio Teams raggruppi automaticamente ogni giocatore sotto la propria squadra e sommi i contributi di ciascun giocatore al punteggio della propria squadra, è importante memorizzare e monitorare i punti in una posizione separata per il gameplay basato sui turni, poiché se un giocatore segna e poi esce prima che il turno sia finito, il suo contributo viene dedotto dalla classifica non appena si disconnette dal gioco.

Per garantire che ciò non accada e che ogni contributo verso l'obiettivo della squadra venga preservato, ReplicatedStorageHUDGuiSetupStartSyncingTeamPoints memorizza tutti i punti separatamente sotto l'attributo teamPoints nel servizio Teams. Man mano che teamPoints aumenta, questo script del modulo chiama la funzione startSyncingTeamPoints per trovare il contatore della squadra Class.GuiObjects all'interno del componente UI Obiettivo.

Quando trova TeamACounter e TeamBCounter, ottiene il loro attributo teamColor, che corrisponde alle zone di spawn della squadra: TeamACounter visualizza i punti della squadra verde e TeamBCounter tiene traccia dei punti della squadra rosa.

StartSyncingTeamPoints
local function startSyncingTeamPoints(gui: ScreenGui)
for _, teamPointCounter in gui.Objective.TeamPointCounter:GetChildren() do
if not teamPointCounter:IsA("GuiObject") then
continue
end
local iconTeamColor = teamPointCounter:GetAttribute(GuiAttribute.teamColor)

Lo script del modulo chiama quindi la sua funzione getTeamFromTeamColor per convalidare che l'attributo teamColor mint di TeamACounter e l'attributo teamColor carnation pink di TeamBCounter corrispondano entrambi alle proprietà Team.Color corrispondenti nel servizio Teams. Se sì, restituisce entrambe le squadre.

StartSyncingTeamPoints
local function getTeamFromTeamColor(teamColor: Color3): Team?
for _, team in Teams:GetTeams() do
if team.TeamColor == teamColor then
return team
end
end
return nil
end

Quando ciò accade, startSyncingTeamPoints imposta gli oggetti TextLabel di entrambi i contatori di squadra sui loro corrispondenti valori di teamPoints e continua ad aggiornarli ogni volta che un giocatore segna un punto eliminando un altro giocatore della squadra avversaria.

StartSyncingTeamPoints
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
team:GetAttributeChangedSignal(GuiAttribute.teamPoints):Connect(function()
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)

Tutto ciò che è stato trattato finora in questa sezione si è concentrato su come tenere traccia dei punti sullo schermo del giocatore, ma è importante rivedere la logica che gestisce il monitoraggio dei punti sul server in modo che sappia quando una squadra raggiunge l'obiettivo e vince il turno. Se torni a ServerScriptServiceGameplayScoring, puoi vedere che lo script del modulo inizia creando un evento bindable, che verrà attivato ogni volta che un giocatore segna un punto.

Scoring
local teamScoreChangedBindable = Instance.new("BindableEvent")
local Scoring = {
teamScoreChanged = teamScoreChangedBindable.Event,
}

Chiama quindi la funzione incrementScore, che esegue le seguenti azioni:

  • Ottiene la squadra del giocatore e il valore attuale di teamPoints sull'oggetto Team nel servizio Teams, quindi aggiunge uno.
  • Ottiene il punteggio individuale del giocatore sulla classifica e aggiunge uno.
  • Attiva l'evento bindable precedentemente menzionato con sia la squadra del giocatore che il loro punteggio.

Questo processo mantiene efficacemente allineati sia il client che il server riguardo ai punteggi individuali dei giocatori e ai punteggi delle loro squadre.

Scoring
function Scoring.incrementScore(player: Player, amount: number)
local team = player.Team
assert(team, `Il giocatore {player.Name} deve essere in una squadra per segnare un punto, ma non ha una squadra`)
local teamPoints = team:GetAttribute(GuiAttribute.teamPoints)
teamPoints += amount
team:SetAttribute(GuiAttribute.teamPoints, teamPoints)
local leaderstat = player.leaderstats.Points
leaderstat.Value += amount
teamScoreChangedBindable:Fire(team, teamPoints)
end

Mostra risultati

Mentre i giocatori si eliminano a vicenda e segnano punti per la loro squadra, ServerScriptServiceGameplayRounds controlla se la squadra che ha segnato ha raggiunto l'obiettivo del turno. Se il punteggio della loro squadra è inferiore alla variabile TEAM_SCORE_LIMIT in ReplicatedStorageTEAM_SCORE_LIMIT, il server continua ad aspettare fino a quando una delle squadre segna di nuovo.

Tuttavia, una volta che il punteggio di una squadra raggiunge la variabile TEAM_SCORE_LIMIT, lo script attiva un'istanza dell'evento roundWinnerRemote con il nome del giocatore e la loro squadra.

Rounds
-- Controlla se il turno è finito dopo ogni punteggio
local team: Team
local score: number = 0
while score < TEAM_SCORE_LIMIT do
team, score = Scoring.teamScoreChanged:Wait()
end
-- Mostra la squadra vincente
for _, player in Players:GetPlayers() do
-- Inviare a quale squadra appartiene il giocatore alla fine del turno
-- perché la squadra del giocatore sta per essere rimossa, quindi il client
-- non sarà in grado di controllare la propria squadra
roundWinnerRemote:FireClient(player, team, player.Team)
end

Lo script ReplicatedStorageRoundResultsGuiSetup su ogni client ascolta questa istanza dell'evento roundWinnerRemote in modo da poter:

  • Visualizzare una schermata UI unica StarterGuiRoundResultsGui che annuncia i risultati del turno e se il giocatore era nella squadra vincente.
  • Riprodurre un clip audio di vittoria o sconfitta.

Ad esempio, se un giocatore è nella squadra che ha segnato il punto vincente, riceve molte forme di feedback sui risultati del turno sotto forma di una schermata UI che visualizza un testo di vittoria e un clip audio che riproduce un suono gioioso. Al contrario, se un giocatore non è nella squadra che ha segnato il punto vincente, riceve una schermata UI che visualizza un testo di sconfitta e un clip audio che riproduce un suono minaccioso.

Feedback di vittoria
Feedback di sconfitta
RoundResultsGuiSetup
local function onRoundWinner(winner: Team, localTeam: Team?)
local victoryDefeatText = "Turno finito!"
if localTeam then
-- Se la nostra squadra ha vinto, visualizzeremo Vittoria! Altrimenti visualizzeremo Sconfitta...
local isVictory = winner == localTeam
if isVictory then
victorySound:Play()
victoryDefeatText = VICTORY_TEXT
else
defeatSound:Play()
victoryDefeatText = DEFEAT_TEXT
end
end

Resetta squadre

Allo stesso tempo in cui ServerScriptServiceGameplayRounds verifica che una squadra abbia raggiunto l'obiettivo del turno e attiva la visualizzazione UI appropriata per ogni giocatore, trasporta anche tutti i giocatori dall'arena al lobby disconnettendoli dal turno. Questo avvia il processo di conclusione formale del turno e resetta entrambe le squadre.

Utilizzando la stessa logica in Configura le posizioni di spawn, Rounds imposta la proprietà Neutral della posizione di spawn Neutra su true in modo che i giocatori possano spawnare lì indipendentemente dal loro stato di squadra. Ciò significa che il lobby diventa l'unica posizione in cui i giocatori possono spawnare dopo essere stati disconnessi dal turno.

Rounds
-- Invia tutti al lobby
playerAddedConnection:Disconnect()
neutralSpawn.Neutral = true
spawnPlayersInLobby(Players:GetPlayers())

Dopo aver atteso dieci secondi per un'interruzione, lo script del server Rounds inizia quindi di nuovo il ciclo resettando i punteggi di tutti e suddividendoli in nuove squadre. L'esempio ripete questo processo ciclico di turni fino a quando non ci sono più giocatori nel server.

Ora che i giocatori possono spawnare nella mappa con la propria squadra e giocare un turno completo, la prossima sezione ti insegna gli script dietro il comportamento di ciascun blaster.

© 2026 Roblox Corporation. Roblox, il logo Roblox e Powering Imagination sono tra i nostri marchi registrati e non registrati negli Stati Uniti. e altri paesi.