Almacenes de datos son un servicio que puedes usar para guardar y cargar datos persistentes de los jugadores a lo largo de diferentes sesiones de juego. Estos almacenan información importante, como el progreso o el inventario de un jugador, y te permiten recuperarla la próxima vez que se una a tu juego. Sin almacenes de datos, un jugador perdería todo su progreso cada vez que sale del juego.
Hay dos tipos de almacenes de datos: estándar y ordenados. Este tutorial utiliza almacenes de datos ordenados, que almacenan datos que puedes clasificar y ordenar numéricamente y recuperar en orden ascendente o descendente según los valores numéricos almacenados.
Usando el archivo Gold Rush create leaderboard tutorial - Start .rbxl como punto de partida y el archivo Gold Rush create leaderboard tutorial - Complete .rbxl como referencia, este tutorial te brinda la base que necesitas para crear un marcador personalizado para los jugadores, incluyendo orientación sobre:
- Almacenar puntajes de oro en un almacén de datos ordenado.
- Recuperar y ordenar los mejores puntajes globalmente en todos los servidores.
- Mostrar los mejores puntajes en un marcador personalizado en la interfaz de usuario.
- Actualizar automáticamente el marcador personalizado cada pocos segundos.
Al final de este tutorial, deberías tener lo siguiente:
- En ServerScriptService:
- Un script GoldManager actualizado que guarda el puntaje del jugador en un almacén de datos ordenado para el marcador.
- Un nuevo script de módulo LeaderboardRemoteHandler que recupera y devuelve la lista ordenada de los mejores puntajes del marcador.
- Un nuevo script LeaderboardManager que responde a las solicitudes de datos del marcador desde el cliente, actuando como un puente entre el cliente en LeaderboardGuiScript y el servidor en LeaderboardManager.
- En StarterGui, un nuevo script local LeaderboardGuiScript que renderiza la interfaz de usuario del marcador para el jugador.

Habilitar acceso del Studio a los servicios API
Los almacenes de datos no se almacenan localmente en tu dispositivo, por lo que tu juego depende de la comunicación servidor a servidor con el backend de Roblox para poder utilizarlos. Por defecto, Studio restringe esta comunicación para prevenir abusos o usos accidentales. El acceso a los servicios API en Studio está deshabilitado hasta que lo habilites explícitamente para asegurarte de que solo los juegos de confianza puedan leer y escribir en los servidores backend de Roblox.
Para habilitar el acceso del Studio a los servicios API para que puedas utilizar almacenes de datos:
- Abre el archivo Gold Rush create leaderboard tutorial - Start en Studio. Este archivo de punto de partida ya incluye el código del tutorial Guardar datos del jugador y el esqueleto de la interfaz de usuario para el marcador de jugadores.
- Regresa a Studio, ve a Archivo ⟩ Configuración de la experiencia ⟩ Seguridad.
- Activa Habilitar acceso del Studio a los servicios API.
- Guarda tus cambios.
Crear un almacén de datos ordenado
Al crear un almacén de datos, siempre debes llamar a DataStoreService desde un Script del lado del servidor. Hacerlo es importante porque:
- Roblox bloquea todo acceso al almacén de datos desde el cliente para que solo el servidor tenga permiso para acceder y modificar los datos persistentes del jugador.
- Los scripts del lado del servidor se ejecutan en un entorno centralizado, asegurando que los datos que se leen y escriben en tu almacén de datos sean precisos y válidos.
- Dado que los scripts del lado del cliente se ejecutan en el dispositivo del jugador, cualquier jugador podría potencialmente explotar el juego y robar o sobrescribir los datos de otros jugadores si el cliente tuviera acceso a tus almacenes de datos.
También debes darle a tu almacén de datos un nombre único para mantener tus datos organizados y prevenir que se superponga o entre en conflicto con diferentes almacenes de datos. En este tutorial, el almacén de datos para el marcador se llama GlobalLeaderboard.
Para crear el almacén de datos ordenado GlobalLeaderboard:
Abre el script existente GoldManager en ServerScriptService.

Bajo el almacén de datos existente PlayerGold, llama a GetOrderedDataStore con la cadena "GlobalLeaderboard". Esto crea un almacén de datos ordenado para guardar el puntaje del jugador cuando gana oro.
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
Después de crear un almacén de datos, puedes hacer referencia a este mismo almacén de datos en diferentes scripts. Por ejemplo, puedes llamar a GetOrderedDataStore tanto en el script GoldManager como en el script de módulo LeaderboardManager que crearás más adelante en este tutorial. Hacer referencia al mismo almacén de datos en dos lugares no significa que estás duplicando datos; simplemente significa que dos scripts están accediendo al mismo almacenamiento centralizado, como dos compañeros de equipo utilizando una carpeta para compartir información.
Enviar datos de jugadores al marcador
Los almacenes de datos están compuestos de claves, que identifican datos, y valores, que almacenan datos. A diferencia de los almacenes de datos estándar, los almacenes de datos ordenados te permiten ordenar datos por valor, lo que los hace ideales para crear cosas como marcadores.
Cada entrada en un almacén de datos ordenado se almacena bajo una clave única que puedes clasificar y ordenar numéricamente, y luego recuperar en orden ascendente o descendente según los valores numéricos almacenados. Esto significa que puedes usar almacenes de datos ordenados para, por ejemplo, mostrar una lista de los 3 mejores que se actualiza en tiempo real a medida que los jugadores en tu juego recolectan más oro.
| Clave | Valor | |
|---|---|---|
| Descripción | Una clave es un identificador de cadena único que puedes usar para acceder a una pieza específica de datos, como el ID de usuario de un jugador. Las claves te permiten organizar tus datos para que puedas gestionarlos y depurarlos fácilmente. | Un valor es el dato numérico real que deseas guardar o cargar, como el puntaje de un jugador. Los valores te permiten almacenar el progreso entre sesiones, así como recuperar datos de los jugadores la próxima vez que se unan a tu juego. |
| Formatos permitidos | Solo pueden ser cadenas. Si estás utilizando números, como un ID de usuario, conviértelos a una cadena usando tostring(). | Solo pueden ser números. |
| Ejemplos | "Player_A", "TopScore", "123456" (ID de usuario como cadena) | 100, 3.14, 0, -25 |
Ahora que has creado tu almacén de datos ordenado GlobalLeaderboard, actualiza la función existente saveGold en el script GoldManager para enviar el puntaje de oro del jugador a tu marcador personalizado con SetAsync:
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("No se pudo guardar el oro de", player.Name, ":", err)
end
end
Puedes pensar en el almacén de datos ordenado GlobalLeaderboard como una carpeta compartida: SetAsync añade contenido a la carpeta, mientras que GetSortedAsync (que crearás más adelante en el script del módulo LeaderboardManager) lee el contenido de la carpeta y lo clasifica por puntaje.
Recuperar los puntajes del marcador
Para recuperar los puntajes del marcador, deberías usar un ModuleScript. Los scripts de módulo te permiten organizar y reutilizar tu código en múltiples scripts. En lugar de copiar la misma lógica en diferentes lugares, puedes escribirla una vez en un script de módulo y llamarla desde cualquier lugar que la necesite.
Cuando almacenas la lógica de tu marcador en un módulo, tanto el manejador de la interfaz de usuario como los scripts del servidor pueden usar la misma función para recuperar los puntajes de los mejores jugadores. Si alguna vez necesitas, por ejemplo, actualizar cómo se recuperan los nombres de usuario o cómo se ordenan los puntajes, solo tienes que cambiar el código en un lugar. Después de que actualices el módulo, todos los scripts que lo utilicen también obtendrán automáticamente el comportamiento actualizado.
Tu marcador personalizado utiliza los siguientes métodos de almacén de datos ordenados para compartir datos a través de diferentes servidores:
- SetAsync (del script GoldManager) para enviar los puntajes de los jugadores al almacén de datos ordenado GlobalLeaderboard.
- GetSortedAsync (en el script de módulo) para recuperar los mejores puntajes de todos los servidores desde el mismo almacén de datos. El método GetSortedAsync es exclusivo de los almacenes de datos ordenados y puede recuperar múltiples claves clasificadas según un orden de clasificación específico, tamaño de página y valores mínimo y máximo.
Para recuperar los puntajes del marcador:
Bajo ServerScriptService, crea un nuevo ModuleScript llamado LeaderboardManager.
En la parte superior del script de módulo, llama a GetOrderedDataStore con la cadena "GlobalLeaderboard". Referenciar el mismo almacén de datos ordenado que creaste en el script GoldManager permitirá que la interfaz de usuario del marcador recupere y ordene los puntajes de los mejores jugadores más adelante.
local DataStoreService = game:GetService("DataStoreService")local Players = game:GetService("Players")local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")Prepara una tabla de módulo para almacenar todas las funciones y datos que deseas exponer a otros scripts.
local leaderboardManager = {}Crea una función llamada GetTopScores para obtener los puntajes de los mejores jugadores. Esta función:
- Llama a GetSortedAsync para recuperar el número limit de los mejores puntajes en orden descendente. Si la llamada falla, se devuelve una lista vacía para evitar que el resto de tu código se bloquee.
- Recorre el marcador para obtener una tabla de entradas con GetCurrentPage y nombres de usuario de jugadores con GetNameFromUserIdAsync.
- Agrega cada resultado a una lista final y construye una tabla de marcador con nombres de usuario de jugadores y sus puntajes.
- Devuelve la lista final de jugadores y envía los datos del marcador de vuelta a cualquier script que llame a esta función leaderboardManager.GetTopScores.
function leaderboardManager.GetTopScores(limit)local success, pages = pcall(function()return leaderboardStore:GetSortedAsync(false, limit)end)if not success or not pages thenreturn {}endlocal results = {}for _, entry in ipairs(pages:GetCurrentPage()) dolocal userId = tonumber(entry.key)local score = entry.valuelocal username = "Desconocido"local ok, name = pcall(function()return Players:GetNameFromUserIdAsync(userId)end)if ok thenusername = nameendtable.insert(results, {Username = username,Score = score})endreturn resultsendHaz que el módulo sea utilizable devolviendo la tabla de módulo que creaste anteriormente. Siempre que creas un script de módulo, debes devolver la tabla de módulo para que otros scripts puedan acceder a ella y llamar a las funciones que contiene.
return leaderboardManager
Solicitar datos del marcador desde el servidor
Para que la interfaz de usuario del cliente muestre los puntajes del marcador, el servidor debe responder cuando el cliente solicite datos. Un RemoteFunction permite que el cliente solicite información al servidor y espere una respuesta.
Para solicitar datos del marcador desde el servidor:
- Bajo ReplicatedStorage, inserta un RemoteFunction llamado LeaderboardRemote. Esta función remota actúa como el puente entre el script de interfaz de usuario en el cliente y la lógica del marcador en el servidor.
- Bajo ServerScriptService, crea un script llamado LeaderboardRemoteHandler. En este script:
Llama a ReplicatedStorage (el espacio compartido entre cliente y servidor), ServerScriptService (que contiene el módulo del marcador) y leaderboardRemote (la función remota que el cliente llamará para solicitar los datos del marcador).
local ReplicatedStorage = game:GetService("ReplicatedStorage")local ServerScriptService = game:GetService("ServerScriptService")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Carga el módulo LeaderboardManager que creaste anteriormente, que incluye la función que obtiene los mejores puntajes del almacén de datos ordenado.
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))Establece el comportamiento para cuando el cliente llame a InvokeServer. El servidor responde recuperando los 3 mejores puntajes y enviando el resultado de vuelta al cliente.
leaderboardRemote.OnServerInvoke = function(player)return leaderboardManager.GetTopScores(3)end
Mostrar datos en la interfaz de usuario del marcador personalizada
Después de configurar los scripts del lado del servidor, crea un script local para recuperar los 3 mejores jugadores cada 3 segundos y mostrar los resultados en un marcador global dentro del juego.
Para mostrar datos en tu marcador personalizado:
Bajo StarterGui ⟩ LeaderboardGui, crea un script local llamado LeaderboardGuiScript.
En la parte superior del script, conéctate a la función remota. Llama a ReplicatedStorage para acceder a los objetos compartidos entre el servidor y el cliente, luego llama a leaderboardRemote para permitir que el cliente solicite los datos del marcador del servidor.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Haz referencia a los elementos existentes de la interfaz de usuario del marcador bajo LeaderboardGui.
local gui = script.Parentlocal leaderboardFrame = gui:WaitForChild("LeaderboardFrame")local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame")local template = entriesFrame:WaitForChild("LeaderboardEntry")Crea una función llamada clearEntries para limpiar las entradas antiguas del marcador. Esta función recorre todos los hijos de entriesFrame, que contiene las filas del marcador, y se asegura de que el marcador se refresque por completo antes de mostrar nuevos datos.
local function clearEntries()for _, child in ipairs(entriesFrame:GetChildren()) doif child:IsA("TextLabel") and child.Name:match("^Row%d+$") thenchild:Destroy()endendendCrea una función llamada renderLeaderboard para insertar y mostrar los datos de los jugadores en las filas del marcador. El objeto data es una tabla devuelta por el servidor que contiene entradas con los nombres de usuario de los jugadores y sus puntajes.
local function renderLeaderboard(data)clearEntries()for i, entry in ipairs(data) dolocal row = template:Clone()row.Name = "Row" .. irow.Visible = truerow.LayoutOrder = irow.Text = string.format("%d%s lugar: %s - %d",i, i == 1 and "o" or i == 2 and "do" or i == 3 and "ro" or "to",entry.Username, entry.Score)row.Parent = entriesFrameendendCrea un bucle para recuperar periódicamente los datos del marcador. Cada 3 segundos, el bucle se ejecuta y llama al servidor utilizando la función InvokeServer que creaste anteriormente en el script LeaderboardRemoteHandler. Si la llamada es exitosa, la interfaz de usuario se refresca con los puntajes actualizados.
while true dolocal success, data = pcall(function()return leaderboardRemote:InvokeServer()end)if success and data thenrenderLeaderboard(data)endtask.wait(3)end
Código final
Consulta los siguientes fragmentos de código para los scripts completos de GoldManager, LeaderboardManager, LeaderboardRemoteHandler y LeaderboardGuiScript. Puedes copiarlos y ejecutarlos directamente en el archivo Gold Rush create leaderboard tutorial - Start .rbxl en Studio.
GoldManager
El script GoldManager crea un almacén de datos ordenado para gestionar las actualizaciones del marcador.
-- Obtener servicios
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local DataStoreService = game:GetService("DataStoreService")
-- Evento remoto para actualizar la interfaz de usuario
local uiEvent = ReplicatedStorage:WaitForChild("UIEvent")
-- Almacén de datos para guardar las piezas de oro del jugador
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Almacén de datos ordenado para guardar el oro en el marcador
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Crear un generador de números aleatorios para posicionar las piezas de oro
local random = Random.new()
-- Tabla para almacenar las piezas de oro del jugador durante una sola sesión
local playerGold = {}
-- Constantes
local GOLD_VALUE = 10 -- Cuánto vale cada pieza de oro
local GOLD_REGENERATION_BOUNDS = { -- Límites de área utilizados para reposicionar las piezas de oro aleatoriamente
minX = -72,
maxX = 72,
minZ = -72,
maxZ = 72
}
local GOLD_REGEN_DELAY = 2 -- El retraso antes de que una pieza vuelva a aparecer (en segundos)
local AUTOSAVE_INTERVAL = 30 -- Con qué frecuencia se guardan las piezas del jugador (en segundos)
-- Función para manejar el momento en que el jugador recolecta una pieza de oro
local function processGoldTouch(chunk, player)
-- Oculta la pieza cuando el jugador la recoge
chunk.Parent = nil
-- Agrega la pieza al puntaje de oro de la sesión del jugador
local userId = player.UserId
playerGold[userId] = (playerGold[userId] or 0) + GOLD_VALUE
print(player.Name, "ahora tiene", playerGold[userId], "oro")
-- Actualiza la barra de puntaje de la interfaz de usuario para reflejar el nuevo puntaje de oro de esta sesión
uiEvent:FireClient(player, {
gold = playerGold[userId],
doTween = true,
showAlert = false
})
-- Espera un poco y luego vuelve a aparecer la pieza de oro que acaba de ser colectada en una ubicación aleatoria
task.delay(GOLD_REGEN_DELAY, function()
-- Vuelve a aparecer la pieza de oro en una nueva posición aleatoria
local nextPositionX = random:NextInteger(GOLD_REGENERATION_BOUNDS.minX, GOLD_REGENERATION_BOUNDS.maxX)
local nextPositionZ = random:NextInteger(GOLD_REGENERATION_BOUNDS.minZ, GOLD_REGENERATION_BOUNDS.maxZ)
chunk.CFrame = CFrame.new(nextPositionX, 50, nextPositionZ) -- Mover la pieza a una nueva posición
chunk:SetAttribute("DropCollided", false) -- Restablecer cualquier bandera de colisión
chunk.Parent = workspace.GoldChunks
end)
end
-- Bucle a través de todas las partes etiquetadas con "Gold" y conéctalas a la detección de toque
for _, chunk in ipairs(CollectionService:GetTagged("Gold")) do
chunk.Touched:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
processGoldTouch(chunk, player)
end
end)
end
-- Función para guardar el oro del jugador en los almacenes de datos estándar y ordenados
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("No se pudo guardar el oro de", player.Name, ":", err)
end
end
-- Función para manejar el momento en que el jugador se une al juego
local function onPlayerAdded(player)
local userId = player.UserId
print(player.Name, "se ha unido al juego")
-- Intentar cargar el oro del jugador desde el almacén de datos
local success, storedGold = pcall(function()
return goldStore:GetAsync(userId)
end)
-- Establecer el puntaje de oro actual de la sesión usando el valor del almacén de datos para el jugador
local currentGold = if success and storedGold then storedGold else 0
playerGold[userId] = currentGold
-- Actualiza la interfaz de usuario con el valor del almacén de datos para el jugador
uiEvent:FireClient(player, {
gold = currentGold,
doTween = false,
showAlert = not success
})
if success then
print("Cargado", currentGold, "oro para", player.Name)
else
-- Notificar al jugador que su oro no pudo ser cargado
uiEvent:FireClient(player, { showAlert = true })
warn("No se pudo cargar oro para", player.Name)
end
-- Iniciar la corrutina de autoguardado para guardar el oro del jugador cada 30 segundos
coroutine.wrap(function()
while player.Parent do
task.wait(AUTOSAVE_INTERVAL)
if playerGold[userId] then
saveGold(player, playerGold[userId])
print("Guardando automáticamente", playerGold[userId], "oro para", player.Name)
end
end
end)()
end
-- Función para manejar el momento en que el jugador deja el juego
local function onPlayerRemoving(player)
local userId = player.UserId
print(player.Name, "ha dejado el juego")
-- Verifica si se rastreó el oro del jugador
if playerGold[userId] then
-- Guardar el oro del jugador en el almacén de datos antes de que se vaya
saveGold(player, playerGold[userId])
end
end
-- Conecta los eventos de unión y salida de jugadores
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
LeaderboardManager
El script de módulo LeaderboardManager:
- Llama a GetSortedAsync() en el almacén de datos ordenado GlobalLeaderboard.
- Convierte los IDs de usuario en nombres de usuario usando GetNameFromUserIdAsync.
- Devuelve una lista de tablas { Username, Score } para los jugadores mejor clasificados.
- Se llama desde LeaderboardRemoteHandler cada vez que un cliente solicita datos del marcador.
-- Obtener servicios
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- Almacén de datos ordenado para guardar los puntajes del marcador
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Tabla para almacenar los puntajes del marcador
local leaderboardManager = {}
-- Función para devolver los mejores puntajes
function leaderboardManager.GetTopScores(limit)
-- Intentar recuperar una página ordenada de entradas del marcador desde el almacén de datos
local success, pages = pcall(function()
-- false = descendente (los puntajes más altos primero)
return leaderboardStore:GetSortedAsync(false, limit)
end)
-- Si la llamada falla o no devuelve nada, registra una advertencia y devuelve una tabla vacía
if not success or not pages then
warn("No se pudo obtener datos del marcador")
return {}
end
-- Crear una tabla para almacenar los datos de los mejores jugadores
local topPlayers = {}
-- Bucle a través de cada entrada en la página actual de resultados del marcador
for _, entry in ipairs(pages:GetCurrentPage()) do
local userId = tonumber(entry.key) -- Convertir la clave de la entrada a un número (el ID de usuario se almacenó como una cadena)
local score = entry.value -- El valor es el puntaje del jugador (cantidad de oro)
local username = "Desconocido" -- Un nombre predeterminado en caso de que la búsqueda falle
-- Intentar obtener el nombre de usuario del jugador a partir de su ID de usuario
local ok, name = pcall(function()
return Players:GetNameFromUserIdAsync(userId)
end)
-- Si la búsqueda tiene éxito, almacena el nombre de usuario real
if ok then
username = name
end
-- Agrega a este jugador y su puntaje a la lista
table.insert(topPlayers, {
Username = username,
Score = score
})
end
-- Devuelve la lista completa de los mejores jugadores con sus nombres de usuario y puntajes
return topPlayers
end
-- Devuelve el módulo LeaderboardManager para que otros scripts puedan usarlo
return leaderboardManager
LeaderboardRemoteHandler
El script LeaderboardRemoteHandler recupera y devuelve los 3 mejores puntajes al cliente que lo llama.
-- Obtener servicios
local ServerScriptService = game:GetService("ServerScriptService") -- Acceso a módulos del lado del servidor
local ReplicatedStorage = game:GetService("ReplicatedStorage") -- Objetos de comunicación compartidos entre cliente y servidor
-- Esperar la RemoteFunction que utiliza el cliente para solicitar datos del marcador
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Cargar el módulo LeaderboardManager que contiene la función GetTopScores
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))
-- Configurar un controlador para cuando el cliente invoque la función remota del marcador
leaderboardRemote.OnServerInvoke = function(player)
-- Llamar al módulo del marcador para obtener los 3 mejores puntajes y devolverlos al cliente
return leaderboardManager.GetTopScores(3)
end
LeaderboardGuiScript
El script local LeaderboardGuiScript:
- Solicita datos del marcador al servidor cada 3 segundos usando Class.RemoteHandler.InvokeServer|InvokeServer.
- Utiliza una plantilla ocultada LeaderboardEntry para mostrar cada fila del marcador.
- Formatea cada fila como "1o lugar: Nombre de usuario - Puntaje".
- Gestiona la creación, visualización y diseño de las filas del marcador usando UIListLayout.
-- Obtener almacenamiento compartido para acceder a la función remota
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obtener la función remota utilizada para solicitar datos del marcador desde el servidor
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Referencias de la interfaz de usuario
local gui = script.Parent -- El LocalScript bajo el ScreenGui
local leaderboardFrame = gui:WaitForChild("LeaderboardFrame") -- Contenedor principal para el marcador
local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame") -- Marco donde aparecen las entradas del marcador
local template = entriesFrame:WaitForChild("LeaderboardEntry") -- Etiqueta de texto oculta utilizada para crear filas
-- Función para eliminar filas antiguas del marcador (pero no la plantilla)
local function clearEntries()
for _, child in ipairs(entriesFrame:GetChildren()) do
-- Solo destruir etiquetas nombradas "Row1", "Row2", etc. (dejar la plantilla sin tocar)
if child:IsA("TextLabel") and child.Name:match("^Row%d+$") then
child:Destroy()
end
end
end
-- Función para mostrar los datos del marcador en pantalla
local function renderLeaderboard(data)
-- Primero eliminar las filas antiguas
clearEntries()
for i, entry in ipairs(data) do
local row = template:Clone() -- Clonar la plantilla oculta
row.Name = "Row" .. i -- Asignarle un nombre único
row.Visible = true -- Hacerla visible
row.LayoutOrder = i -- Permitir que UIListLayout la ordene correctamente
-- Formato del marcador: "1o lugar: Nombre de usuario - 123"
row.Text = string.format("%d%s lugar: %s - %d",
i,
i == 1 and "o" or i == 2 and "do" or i == 3 and "ro" or "to",
entry.Username,
entry.Score
)
-- Agregar los datos a la interfaz de usuario
row.Parent = entriesFrame
end
end
-- Bucle principal: actualizar el marcador cada 3 segundos
while true do
-- Preguntar al servidor por los datos del marcador
local success, data = pcall(function()
return leaderboardRemote:InvokeServer()
end)
if success and data then
-- Mostrar resultados en el marcador
renderLeaderboard(data)
else
warn("No se pudo obtener los datos del marcador")
end
-- Esperar 3 segundos antes de actualizar nuevamente
task.wait(3)
end