现在您可以检测玩家何时收集了硬币,本教程的这一部分教您如何计算玩家收集了多少硬币,并将该数量显示在排行榜上。
创建模块脚本来记录硬币系列
要处理每个玩家的硬币收集数据的存储和管理,您需要创建一个 ModuleScript 对象来包含每个玩家访问硬币收集数据的数据结构和函数。模块脚本是其他脚本可能1) 必填 2)需要的可重用代码。在这种情况下, CoinService 需要这个模块脚本,以便当玩家触碰硬币时,它可以更新硬币收集数据。
要创建模块脚本:
在 探索器 窗口中,将鼠标悬停在 ServerStorage 上,然后单击 ⊕ 按钮。会话上下文菜单显示。
从上下文菜单中,选择 ModuleScript 。一个新模块脚本显示在 ServerStorage 下。你正在将模块脚本放置到 ServerStorage 中,因为你想管理服务器上的硬币收集逻辑。
将模块脚本重命名为 PlayerData 。
将默认代码替换为以下验证码:
local PlayerData = {}PlayerData.COIN_KEY_NAME = "Coins"local playerData = {--[[[userId: string] = {["Coins"] = coinAmount: number}]]}local DEFAULT_PLAYER_DATA = {[PlayerData.COIN_KEY_NAME] = 0}local function getData(player)local data = playerData[tostring(player.UserId)] or DEFAULT_PLAYER_DATAplayerData[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代码说明模块脚本定义了一个 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 表的数据。如果玩家尚未收集硬币,它将返回一个 DEFAULT_PLAYER_DATA 表,以确保每个玩家都有与他们相关的数据。一个常见的做法是创建简单的、面向公众的函数,将逻辑转移到本地范围的函数来进行重型工作。
local DEFAULT_PLAYER_DATA = {[PlayerData.COIN_KEY_NAME] = 0}local function getData(player)local data = playerData[tostring(player.UserId)] or DEFAULT_PLAYER_DATAplayerData[tostring(player.UserId)] = datareturn dataend定义公共数据访问者
getValue() 和 updateValue() 是面向公众的函数,其他需要此模块脚本的脚本可以调用。在我们的情况下, CoinService 使用这些函数每当玩家触碰硬币时更新玩家的硬币收集数据。
function 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 newValueend
实现排行榜
您可以用屏幕上的排行榜来视觉化代币收集数据。Roblox 包含一个内置系统,可自动使用默认 UI 生成排行榜。
要创建排行榜:
在 探索器 窗口中,在 ServerStorage 中创建一个 ModuleScript ,然后将模块脚本重命名为 排行榜 。
将默认代码替换为以下验证码:
local Leaderboard = {}-- 创建新的排行榜local function setupLeaderboard(player)local leaderstats = Instance.new("Folder")-- ‘leaderstats’是 Roblox 认可的保留名称,用于创建排行榜leaderstats.Name = "leaderstats"leaderstats.Parent = playerreturn leaderstatsend-- 创建新的排行榜统计值local function setupStat(leaderstats, statName)local stat = Instance.new("IntValue")stat.Name = statNamestat.Value = 0stat.Parent = leaderstatsreturn statend-- 更新玩家的状态值function 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代码说明以下部分描述了排行榜在更详细的情况下如何工作。
创建排行榜
setupLeaderboard() 函数创建了一个名为 leaderstats 的新文件夹实例,并将其设为指定玩家的子文件夹。Roblox 会自动识别名为 leaderstats 的文件夹为统计数据容器,并创建一个用于显示统计数据的 UI 元素。它需要在 leaderstats 中的值存储为“值”对象(例如 StringValue 、 IntValue 或 NumberValue)。
-- 创建新的排行榜local function setupLeaderboard(player)local leaderstats = Instance.new("Folder")-- ‘leaderstats’是 Roblox 认可的保留名称,用于创建排行榜leaderstats.Name = "leaderstats"leaderstats.Parent = playerreturn leaderstatsend-- 创建新的排行榜统计值local function setupStat(leaderstats, statName)local stat = Instance.new("IntValue")stat.Name = statNamestat.Value = 0stat.Parent = leaderstatsreturn statend更新玩家数据
setStat() 是 排行榜 模块中唯一的公共函数。如果尚未存在,它会为指定的玩家或排行榜本身创建状态值。
FindFirstChild() 接受对象的名称,并如果存在返回对象,否则返回 nil 。这是一种常见且安全的方法,可以确定在使用之前对象是否存在。
-- 更新玩家的状态值function 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 = valueend
整合模块脚本
完成了 PlayerData 和 Leaderboard 模块脚本,需要在 CoinService 脚本中管理和显示玩家币数据。要更新 金币服务 :
在 浏览器 窗口中,打开 CoinService 脚本。
用以下代码替换现有代验证码:
-- 初始化服务和变量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.Coinslocal coins = coinsFolder:GetChildren()local COIN_KEY_NAME = PlayerData.COIN_KEY_NAMElocal COOLDOWN = 10local COIN_AMOUNT_TO_ADD = 1local 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") thenlocal character = otherPart.Parentlocal player = Players:GetPlayerFromCharacter(character)if player then-- 玩家触碰了一个硬币coin.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-- 设置事件听众for _, coin in coins docoin:SetAttribute("Enabled", true)coin.Touched:Connect(function(otherPart)onCoinTouched(otherPart, coin)end)end代码说明对原始 CoinService 脚本的更改包括:
- 宣言 COIN_AMOUNT_TO_ADD 作为玩家收集硬币时要添加的硬币数量,以及 COIN_KEY_NAME 作为在 PlayerData 中定义的关键名称。
- 创建助助函数 updatePlayerCoins() 来更新玩家的硬币数量和相关排行榜统计数据
- 在 onCoinTouched() 中替换占位符 print() 声明以调用 updatePlayerCoins() 。
游戏测试
是时候看看硬币收集是否按预期运行了。当你触碰并收集游戏中的硬币时,你应该能够在排行榜 UI 上看到你收集的硬币数量。要测试您的体验:
在工具栏中,单击 播放 按钮。Studio 进入游戏测试模式。
将角色移动到触碰硬币。如果你的脚本正常运行,排行榜 UI 会显示并增加你收集更多硬币时的硬币数量。