记录和显示玩家数据

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处


现在你可以检测玩家收集硬币的时刻了,你需要计算玩家收集了多少硬币并在排行榜上显示这一数量。

创建一个模块脚本以记录硬币收集

为了处理每个玩家的硬币收集数据的存储和管理,你需要创建一个 ModuleScript 对象,以包含一个数据结构和访问每个玩家硬币收集数据的函数。模块脚本是可以被其他脚本调用的可重用代码。在这种情况下,CoinService 需要这个模块脚本,以便在玩家触摸硬币时更新硬币收集数据。

创建 PlayerData

在 ServerStorage 中创建一个名为 PlayerData 的 ModuleScript,并添加以下代码:
```lua
local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number
}
]]
}
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
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
return PlayerData
```

模块脚本定义了一个 PlayerData 表,该表包含零个或多个 playerData 表,表示玩家的硬币收集数据。每个需要这个模块脚本的脚本都将接收相同的 PlayerData 表副本,允许多个脚本修改和共享硬币收集数据。

声明数据结构

模块脚本以声明一个空表 PlayerData 开始,该表在脚本结束时返回。它还包含访问器方法以获取和设置表中的值。

playerData 表包含描述表结构的注释,使代码更易于理解。在这种情况下,playerData 表包含一个 userId 和一个对应字段 Coins,表示该玩家收集的硬币数量。


local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number
}
]]
}
...
return PlayerData

定义本地数据访问器

getData() 是一个本地函数,用于检索特定 playerData 表的数据。如果玩家还没有收集硬币,它将返回 defaultPlayerData() 函数中的一个表,以确保每个玩家都有某些相关的数据。一个常见的约定是创建简单的公共函数,将逻辑卸载到本地作用域的函数中来完成繁重的工作。


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

定义公共数据访问器

getValue()updateValue() 是面向公共的函数,其他需要这个模块脚本的脚本可以调用。在我们的例子中,CoinService 使用这些函数在玩家触摸硬币时更新该玩家的硬币收集数据。


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

实现排行榜

你可以通过屏幕上的排行榜以可视化方式呈现硬币收集数据。Roblox 包含一个内置系统,自动生成一个使用默认 UI 的排行榜。

创建排行榜

在 ServerStorage 中创建一个名为 Leaderboard 的 ModuleScript,并添加以下代码:
```lua
local Leaderboard = {}
-- 创建新的排行榜
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats' 是 Roblox 识别的一个保留名称,用于创建排行榜
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- 创建一个新的排行榜统计值
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
end
-- 更新玩家的统计值
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
return Leaderboard
```

以下部分更详细地描述了排行榜的工作原理。

创建排行榜

setupLeaderboard() 函数创建一个名为 leaderstats 的新文件夹实例,并将其设置为指定玩家的子级。Roblox 自动识别名为 leaderstats 的文件夹作为统计数据的容器,并创建一个 UI 元素来显示统计数据。它要求 leaderstats 中的值必须存储为“值”对象(例如 StringValueIntValueNumberValue)。


-- 创建新的排行榜
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats' 是 Roblox 识别的一个保留名称,用于创建排行榜
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- 创建一个新的排行榜统计值
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
end

更新玩家统计数据

setStat()Leaderboard 模块中唯一的公共函数。它为指定玩家或排行榜本身创建统计值(如果它尚不存在)。

FindFirstChild() 接受一个对象的名称,如果存在则返回该对象,如果不存在则返回 nil。这是一个常见的安全方法,可以在使用对象之前检查它是否存在。


-- 更新玩家的统计值
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

集成模块脚本

在两个模块就位后,在 CoinService 脚本中导入它们,以管理和显示玩家硬币数据。

更新 CoinService

在 ServerScriptService 中,用以下代码替换现有 CoinService 脚本的代码:
```lua
-- 初始化服务和变量
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
-- 模块
local Leaderboard = require(ServerStorage.Leaderboard)
local PlayerData = require(ServerStorage.PlayerData)
local coinsFolder = Workspace.World.Coins
local coins = coinsFolder:GetChildren()
local COIN_KEY_NAME = PlayerData.COIN_KEY_NAME
local COOLDOWN = 10
local COIN_AMOUNT_TO_ADD = 1
local function updatePlayerCoins(player, updateFunction)
-- 更新硬币表
local newCoinAmount = PlayerData.updateValue(player, COIN_KEY_NAME, updateFunction)
-- 更新硬币排行榜
Leaderboard.setStat(player, COIN_KEY_NAME, newCoinAmount)
end
-- 定义事件处理器
local function onCoinTouched(otherPart, coin)
if coin:GetAttribute("Enabled") then
local character = otherPart.Parent
local player = Players:GetPlayerFromCharacter(character)
if player then
-- 玩家触碰了硬币
coin.Transparency = 1
coin:SetAttribute("Enabled", false)
updatePlayerCoins(player, function(oldCoinAmount)
oldCoinAmount = oldCoinAmount or 0
return oldCoinAmount + COIN_AMOUNT_TO_ADD
end)
task.wait(COOLDOWN)
coin.Transparency = 0
coin:SetAttribute("Enabled", true)
end
end
end
-- 设置事件监听器
for _, coin in coins do
coin:SetAttribute("Enabled", true)
coin.Touched:Connect(function(otherPart)
onCoinTouched(otherPart, coin)
end)
end
```

对原有 CoinService 脚本的更改包括:

  • 使用 require() 函数导入 PlayerDataLeaderboard 模块。
  • 声明 COIN_AMOUNT_TO_ADD 为玩家收集硬币时要增加的硬币数量,COIN_KEY_NAMEPlayerData 中定义的键名称。
  • 创建助手函数 updatePlayerCoins() 来更新玩家的硬币数量和相关的排行榜统计数据。
  • onCoinTouched() 中用 updatePlayerCoins() 的调用替换占位符 print() 语句。

试玩

从下拉菜单中选择 测试 并点击 播放。走进一个硬币,确认排行榜在角落中出现,并且随着你收集更多硬币,硬币数量增加。

©2026 Roblox Corporation、Roblox、Roblox 标志及 Powering Imagination 是我们在美国及其他国家或地区的注册与未注册商标。