Ahora que puedes detectar cuando un jugador ha recogido una moneda, necesitas contar cuántas monedas han recogido los jugadores y hacer que esa cantidad sea visible en un leaderboard.
Crea un script de módulo para registrar la recolección de monedas
Para manejar el almacenamiento y la gestión de los datos de recolección de monedas de cada jugador, necesitas crear un objeto ModuleScript que contenga una estructura de datos y funciones que accedan a los datos de recolección de monedas para cada jugador. Los scripts de módulo son código reutilizable que otros scripts pueden requerir. En este caso, el CoinService requiere este script de módulo para que pueda actualizar los datos de recolección de monedas cuando los jugadores toquen monedas.
Crear PlayerDataEn ServerStorage, crea un ModuleScript llamado PlayerData con el siguiente código:```lualocal PlayerData = {}PlayerData.COIN_KEY_NAME = "Coins"local playerData = {--[[[userId: string] = {["Coins"] = coinAmount: number}]]}local function defaultPlayerData()return {[PlayerData.COIN_KEY_NAME] = 0}endlocal function getData(player)local data = playerData[tostring(player.UserId)] or defaultPlayerData()playerData[tostring(player.UserId)] = datareturn dataendfunction PlayerData.getValue(player, key)return getData(player)[key]endfunction PlayerData.updateValue(player, key, updateFunction)local data = getData(player)local oldValue = data[key]local newValue = updateFunction(oldValue)data[key] = newValuereturn newValueendreturn PlayerData```
El script de módulo define una tabla PlayerData que contiene cero o más tablas playerData, que representan los datos de recolección de monedas de un jugador. Cada script que requiera este script de módulo recibe la misma copia de la tabla PlayerData, lo que permite que múltiples scripts modifiquen y compartan los datos de recolección de monedas.
Declarar las estructuras de datos
El script de módulo comienza con una declaración de una tabla vacía, PlayerData, que se devuelve al final del script. También contiene métodos de acceso para obtener y establecer valores en la tabla.
La tabla playerData contiene comentarios que describen la estructura de la tabla, lo que hace que el código sea más fácil de entender. En este caso, una tabla playerData contiene un userId y un campo correspondiente llamado Coins que representa la cantidad de monedas recolectadas para ese jugador.
local PlayerData = {}PlayerData.COIN_KEY_NAME = "Coins"local playerData = {--[[[userId: string] = {["Coins"] = coinAmount: number}]]}...return PlayerData
Definir un accesador de datos local
getData() es una función local que recupera datos para una tabla playerData específica. Si un jugador no ha recolectado una moneda, devuelve una tabla de la función defaultPlayerData() para asegurar que cada jugador tenga algunos datos asociados con ellos. Una convención común es crear funciones públicas simples que deleguen lógica a funciones de ámbito local que realicen el trabajo pesado.
local function defaultPlayerData()
return {
[PlayerData.COIN_KEY_NAME] = 0
}
end
local function getData(player)
local data = playerData[tostring(player.UserId)] or defaultPlayerData()
playerData[tostring(player.UserId)] = data
return data
end
Definir accesadores de datos públicos
getValue() y updateValue() son funciones públicas que otros scripts que requieran este script de módulo pueden llamar. En nuestro caso, el CoinService utiliza estas funciones para actualizar los datos de recolección de monedas de un jugador cada vez que ese jugador toca una moneda.
function PlayerData.getValue(player, key)
return getData(player)[key]
end
function PlayerData.updateValue(player, key, updateFunction)
local data = getData(player)
local oldValue = data[key]
local newValue = updateFunction(oldValue)
data[key] = newValue
return newValue
end
Implementar un leaderboard
Puedes representar los datos de recolección de monedas visualmente con un leaderboard en la pantalla. Roblox incluye un sistema incorporado que genera automáticamente un leaderboard utilizando una interfaz de usuario predeterminada.
Crear LeaderboardEn ServerStorage, crea un ModuleScript llamado Leaderboard con el siguiente código:```lualocal Leaderboard = {}-- Creando un nuevo leaderboardlocal function setupLeaderboard(player)local leaderstats = Instance.new("Folder")-- 'leaderstats' es un nombre reservado que Roblox reconoce para crear un leaderboardleaderstats.Name = "leaderstats"leaderstats.Parent = playerreturn leaderstatsend-- Creando un nuevo valor de estado para el leaderboardlocal function setupStat(leaderstats, statName)local stat = Instance.new("IntValue")stat.Name = statNamestat.Value = 0stat.Parent = leaderstatsreturn statend-- Actualizando el valor del estado de un jugadorfunction Leaderboard.setStat(player, statName, value)local leaderstats = player:FindFirstChild("leaderstats")if not leaderstats thenleaderstats = setupLeaderboard(player)endlocal stat = leaderstats:FindFirstChild(statName)if not stat thenstat = setupStat(leaderstats, statName)endstat.Value = valueendreturn Leaderboard```
Las siguientes secciones describen cómo funciona el leaderboard con más detalle.
Crear un leaderboard
La función setupLeaderboard() crea una nueva instancia de carpeta llamada leaderstats y la establece como un hijo del jugador especificado. Roblox reconoce automáticamente una carpeta llamada leaderstats como un contenedor de estadísticas y crea un elemento de interfaz de usuario para mostrar las estadísticas. Requiere que los valores en leaderstats se almacenen como objetos de "valor" (como StringValue, IntValue o NumberValue).
-- Creando un nuevo leaderboard
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats' es un nombre reservado que Roblox reconoce para crear un leaderboard
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- Creando un nuevo valor de estado para el leaderboard
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
end
Actualizar estadísticas de los jugadores
setStat() es la única función pública en el módulo Leaderboard. Crea valores de estado para un jugador especificado o para el leaderboard mismo si aún no existen.
FindFirstChild() toma el nombre de un objeto y devuelve el objeto si existe, o nil si no existe. Es un método común y seguro de averiguar si un objeto existe antes de usarlo.
-- Actualizando el valor del estado de un jugador
function Leaderboard.setStat(player, statName, value)
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = setupLeaderboard(player)
end
local stat = leaderstats:FindFirstChild(statName)
if not stat then
stat = setupStat(leaderstats, statName)
end
stat.Value = value
end
Integrar los scripts de módulo
Con ambos módulos en su lugar, requiéralos en el script de CoinService para gestionar y mostrar los datos de monedas de los jugadores.
Actualizar CoinServiceEn ServerScriptService, reemplaza el código existente del script CoinService con el siguiente:```lua-- Inicializando servicios y variableslocal Workspace = game:GetService("Workspace")local Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")-- Móduloslocal Leaderboard = require(ServerStorage.Leaderboard)local PlayerData = require(ServerStorage.PlayerData)local coinsFolder = Workspace.World.Coinslocal coins = coinsFolder:GetChildren()local COIN_KEY_NAME = PlayerData.COIN_KEY_NAMElocal COOLDOWN = 10local COIN_AMOUNT_TO_ADD = 1local function updatePlayerCoins(player, updateFunction)-- Actualizar la tabla de monedaslocal newCoinAmount = PlayerData.updateValue(player, COIN_KEY_NAME, updateFunction)-- Actualizar el leaderboard de monedasLeaderboard.setStat(player, COIN_KEY_NAME, newCoinAmount)end-- Definiendo el manejador de eventoslocal function onCoinTouched(otherPart, coin)if coin:GetAttribute("Enabled") thenlocal character = otherPart.Parentlocal player = Players:GetPlayerFromCharacter(character)if player then-- El jugador tocó una monedacoin.Transparency = 1coin:SetAttribute("Enabled", false)updatePlayerCoins(player, function(oldCoinAmount)oldCoinAmount = oldCoinAmount or 0return oldCoinAmount + COIN_AMOUNT_TO_ADDend)task.wait(COOLDOWN)coin.Transparency = 0coin:SetAttribute("Enabled", true)endendend-- Configurando escuchadores de eventosfor _, coin in coins docoin:SetAttribute("Enabled", true)coin.Touched:Connect(function(otherPart)onCoinTouched(otherPart, coin)end)end```
Los cambios en el script original de CoinService incluyen:
- Declarar COIN_AMOUNT_TO_ADD como el número de monedas a agregar cuando un jugador recolecta una moneda, y COIN_KEY_NAME como la clave definida en PlayerData.
- Crear la función auxiliar updatePlayerCoins() para actualizar la cuenta de monedas del jugador y la estadística del leaderboard asociada.
- Reemplazar la declaración de print() en onCoinTouched() con una llamada a updatePlayerCoins().
Pruebas de juego
Selecciona Test en el menú desplegable y haz clic en Play. Camina hacia una moneda y confirma que el leaderboard aparece en la esquina y que tu cuenta de monedas aumenta a medida que recoges más monedas.