Añadir rondas te permite estructurar el juego en fases con un punto de inicio y final claro para que los jugadores puedan medir su progreso y tengan una oportunidad periódica para un campo de juego igualitario.Esto es particularmente importante para el juego basado en equipos porque ofrece a los jugadores la posibilidad de cambiar su estilo de juego dependiendo de quién esté en su equipo durante esa ronda.
Usando la experiencia de etiqueta láser de muestra como referencia, esta sección del tutorial te enseña cómo usar y personalizar las funciones integradas de Roblox para estructurar cada ronda, incluyendo instrucciones de programación sobre:
- Comenzar una ronda restableciendo puntos individuales y de equipo, luego generando jugadores en las zonas de generación de equipos.
- Personalización de variables que establecen el objetivo para la ronda en la parte superior de la pantalla de cada jugador.
- Rastrear contribuciones de puntos del jugador para la puntuación de su equipo.
- Activar pantallas de interfaz de usuario únicas dependiendo de si el equipo del jugador ganó o perdió la ronda.
- Terminar una ronda desconectando a los jugadores y generándolos en el vestíbulo neutral.
Después de completar esta sección, aprenderás cómo implementar el comportamiento de los blásteres que sea tanto preciso como satisfactorio para los jugadores.

Iniciar bucle
Servicio de script de servidor > Juego > Rondas maneja la mayor parte de la lógica para implementar rondas, y comienza llamando la función startRoundLoopAsync() para marcar el comienzo de un ciclo de rondas.Mientras los jugadores se unen al vestíbulo y esperan para ser asignados a un equipo, llama a la función en ServerScriptService > Juego > Puntuación para restablecer tanto la tabla de clasificación como los puntos del equipo.
Calificación
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
Ahora que todos están comenzando en cero puntos, luego establece la propiedad Neutral de la ubicación de generación de neutra en falso para que solo los jugadores con la misma propiedad que la ubicación de generación de puedan aparecer allí.Debido a que la propiedad de la lugar de regeneraciónde generación TeamColor se establece en blanco en lugar de los equipos de menta o carnación rosa de la muestra, esta configuración impide que todos los jugadores se generen o reaparezcan allí mientras una ronda está activa.
Para los jugadores que están actualmente en el vestíbulo, startRoundLoopAsync() pasa todos los jugadores actualmente dentro de la experiencia a la función spawnPlayersInMap de Servicio de script del servidor > juego > rondas > generar jugadores en el mapa para ordenar y equilibrar a todos en un equipo con aproximadamente el mismo número de jugadores.
Para cualquier nuevo jugador que se una a la experiencia después de que el grupo del vestíbulo se clasificara en un equipo, startRoundLoopAsync() escucha el evento Players.PlayerAdded:Connect y luego llama de nuevo a la función spawnPlayersInMap para agregarlos al equipo con la menor cantidad de jugadores.Para obtener más información sobre este proceso, consulte Configurar ubicaciones de generación de la sección anterior Generación y reaparición del tutorial.
Rondas
-- Genera a todos los jugadores en el mapa
neutralSpawn.Neutral = false
spawnPlayersInMap(Players:GetPlayers())
-- Genera nuevos jugadores en el mapa cuando se unan
local playerAddedConnection = Players.PlayerAdded:Connect(function(player: Player)
spawnPlayersInMap({ player })
end)
Establecer objetivo
Ahora que cada jugador está en la arena con sus compañeros de equipo, la experiencia debe proporcionar instrucciones para qué hacer para tener éxito dentro de la ronda.La experiencia de etiqueta láser de muestra aborda este requisito al proporcionar una solicitud objetiva en la parte superior de la pantalla de cada jugador con instrucciones claras sobre lo que el equipo debe hacer para ganar.

Aunque puedes aprender más sobre cómo configurar y mostrar el componente de Interfaz de usuario objetivo en el currículum de la interfaz de usuario, esta sección se centra en cómo implementar el objetivo del objetivo a medida que comienza la ronda, comenzando con cómo establecer la cantidad de puntos que cada equipo necesita para completar la ronda.
Aunque el mensaje de objetivo en tiempo de ejecución informa a los jugadores que necesitan anotar tres puntos para ganar, si examinas el mensaje en StarterGui > HUDGui , puedes ver que contiene un configurable " %d " para el valor del punto.

"" %d "es una cadena de marcador que puedes aumentar o disminuir en cualquier momento para cumplir con tus propios requisitos de juego actualizando la variable TEAM_SCORE_LIMIT en ReplicatedStorage > LÍMITE_PUNTUACIÓN_EQUIPO .Por ejemplo, si estableces este número a un excesivamente alto 200 , el contador de puntos de alerta y equipo se actualizaría en consecuencia.
Límite de puntuación de equipo
local TEAM_SCORE_LIMIT = 200 -- línea actualizada, asegúrate de cambiar de volverreturn TEAM_SCORE_LIMIT

Esta sencilla actualización de variable funciona en tiempo de ejecución porque cuando comienza la ronda, ReplicatedStorage > HUDGuiSetup > Establecer objetivo requiere el script del módulo para que pueda intercambiar la cadena de marcador en el objeto de objetivo de la interfaz de usuario.
Límite de puntuación de equipo
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
Puntos de seguimiento
Ahora que los jugadores tienen un objetivo para la ronda, la experiencia debe realizar un seguimiento de los puntos de cada equipo hasta que cumplan con su objetivo.Mientras que el comportamiento predeterminado del servicio Teams agrupa automáticamente a cada jugador debajo de su equipo y suma las contribuciones de cada jugador a su puntaje de equipo, es importante almacenar y monitorear los puntos en una ubicación separada para el juego basado en rondas porque si un jugador anota, luego se va antes de que termine la ronda, sus contribuciones se deducen de la tabla de clasificación tan pronto como se desconecte de la experiencia.
Para garantizar que esto no suceda y que cada contribución hacia el objetivo del equipo se preserve, ReplicatedStorage > HUDGuiSetup > Iniciar sincronización de puntos de equipo almacena todos los puntos por separado bajo la atribución en el servicio.Como teamPoints incrementos, este script de módulo llama a la función startSyncingTeamPoints para encontrar el contador de equipos Class.GuiObjects dentro del componente de interfaz de usuario objetivo.
Cuando localiza TeamACounter y TeamBCounter , obtiene su atributo teamColor, que se correlaciona con las zonas de generación de equipos: TeamACounter muestra los puntos del equipo verde, y TeamBCounter rastrea los puntos del equipo rosa.
Comenzar a sincronizar puntos de equipo
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)
El script del módulo luego llama a su función de validación para validar que el atributo menta de TeamACounter y el atributo carnación rosa de TeamBCounter coincidan con las correspondientes propiedades de servicio debajo del servicio.Si es así, devuelve a ambos equipos.
Comenzar a sincronizar puntos de equipo
local function getTeamFromTeamColor(teamColor: Color3): Team?
for _, team in Teams:GetTeams() do
if team.TeamColor == teamColor then
return team
end
end
return nil
end
Cuando ocurre esto, startSyncingTeamPoints configura los objetos de ambos contadores de equipo TextLabel a sus correspondientes valores de teamPoints, y continúa actualizándolos cada vez que un jugador marque un punto etiquetando a otro jugador del equipo opuesto.
Comenzar a sincronizar puntos de equipo
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
team:GetAttributeChangedSignal(GuiAttribute.teamPoints):Connect(function()
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
Todo en esta sección hasta ahora se ha centrado en cómo rastrear puntos en la pantalla del jugador, pero es importante revisar la lógica que maneja los puntos de seguimiento en el servidor para que sepa cuándo un equipo cumple con el objetivo y gana la ronda.Si vuelves a visitar Servicio de guiones de servidor > Juego > Calificación , puedes ver que el script del módulo comienza creando un evento vinculable, que se disparará cada vez que un jugador marque un punto.
Calificación
local teamScoreChangedBindable = Instance.new("BindableEvent")local Scoring = {teamScoreChanged = teamScoreChangedBindable.Event,}
Luego llama a la función incrementScore, que realiza las siguientes acciones:
- Agarra el equipo del jugador y su valor actual de puntos de equipo en el objeto del servicio, luego agrega uno.
- Agarra la puntuación individual del jugador en la tabla de clasificación y agrega uno.
- Dispara el evento mencionado anteriormente con ambos equipos del jugador y su puntuación.
Este proceso mantiene efectivamente alineados tanto al cliente como al servidor con respecto a las puntuaciones individuales de ambos jugadores y sus puntuaciones de equipo.
Calificación
function Scoring.incrementScore(player: Player, amount: number)
local team = player.Team
assert(team, `Player {player.Name} must be on a team to score a point, but has no team`)
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
Mostrar resultados
A medida que los jugadores se etiquetan entre sí y anotan puntos para su equipo, ServerScriptService > Juego > Rondas comprueba si el equipo que anotó cumplió con el objetivo de la ronda.Si la puntuación de su equipo es inferior a la variable TEAM_SCORE_LIMIT de ReplicatedStorage > TEAM_SCORE_LIMIT , el servidor sigue esperando hasta que uno de los equipos marque de nuevo.
Sin embargo, una vez que la puntuación de un equipo llega a la variable TEAM_SCORE_LIMIT, el script activa una instancia de evento roundWinnerRemote con el nombre del jugador y su equipo.
Rondas
-- Compruebe si la ronda se ha terminado después de cada puntuaciónlocal team: Teamlocal score: number = 0while score < TEAM_SCORE_LIMIT doteam, score = Scoring.teamScoreChanged:Wait()end-- Mostrar equipo ganadorfor _, player in Players:GetPlayers() do-- Enviar a qué equipo está el jugador al final de la ronda-- porque el equipo del jugador está a punto de ser eliminado, por lo que el cliente-- no podrá verificar su propio equiporoundWinnerRemote:FireClient(player, team, player.Team)end
El script ReplicatedStorage > RoundResultsGuiSetup en cada lista de clientes escucha esta instancia de evento para que pueda:
- Muestra una pantalla de interfaz de usuario única StarterGui > RoundResultsGui que anuncia los resultados de la ronda y si el jugador estaba en el equipo ganador.
- Reproduce un clip de audio de victoria o derrota.
Por ejemplo, si un jugador está en el equipo que marcó el punto ganador, recibe múltiples formas de comentarios sobre los resultados de la ronda en forma de una pantalla de interfaz de usuario que muestra el texto de la victoria y un archivo de audio que reproduce un sonido alegre.Al revés, si un jugador no está en el equipo que marcó el punto ganador, reciben una pantalla de interfaz de usuario que muestra el texto de derrota y un archivo de audio que reproduce un sonido ominoso.
Configuración de RoundResultsGui
local function onRoundWinner(winner: Team, localTeam: Team?)
local victoryDefeatText = "Round ended!"
if localTeam then
-- Si nuestro equipo gana, mostraremos la victoria! De lo contrario, mostraremos la derrota...
local isVictory = winner == localTeam
if isVictory then
victorySound:Play()
victoryDefeatText = VICTORY_TEXT
else
defeatSound:Play()
victoryDefeatText = DEFEAT_TEXT
end
end
Reiniciar equipos
Al mismo tiempo que ServerScriptService > Gameplay > Rondas verifica que un equipo cumplió con el objetivo de la ronda y activa la interfaz de usuario apropiada para cada jugador, también transporta a todos los jugadores de la arena al vestíbulo al desconectarlos de la ronda.Esto inicia el proceso de terminar formalmente la ronda y reiniciar ambos equipos.
Al usar la misma lógica en Configurar ubicaciones de generación , rondas luego establece la propiedad neutral de la ubicación de generación cero para que los jugadores puedan aparecer allí independientemente del estado de su equipo.Esto significa que el vestíbulo se convierte en la única ubicación en la que los jugadores pueden aparecer después de que se desconecten de la ronda.
Rondas
-- Enviar a todos al vestíbuloplayerAddedConnection:Disconnect()neutralSpawn.Neutral = truespawnPlayersInLobby(Players:GetPlayers())
Después de esperar diez segundos por un intermedio, el script del servidor Rondas comienza el ciclo nuevamente al restablecer las puntuaciones de todos y ordenarlas en nuevos equipos.La muestra repite este proceso cíclico hasta que no haya ningún jugador dentro del servidor.
Ahora que los jugadores pueden generarse en el mapa con su propio equipo y jugar una ronda completa, la siguiente sección te enseña sobre los scripts detrás del comportamiento de cada bláster.