记录和显示玩家数据

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


现在您可以检测玩家何时收集了硬币,本教程的这一部分教您如何计算玩家收集了多少硬币,并将该数量显示在排行榜上。

创建模块脚本来记录硬币系列

要处理每个玩家的硬币收集数据的存储和管理,您需要创建一个 ModuleScript 对象来包含每个玩家访问硬币收集数据的数据结构和函数。模块脚本是其他脚本可能1) 必填 2)需要的可重用代码。在这种情况下, CoinService 需要这个模块脚本,以便当玩家触碰硬币时,它可以更新硬币收集数据。

要创建模块脚本:

  1. 探索器 窗口中,将鼠标悬停在 ServerStorage 上,然后单击 按钮。会话上下文菜单显示。

  2. 从上下文菜单中,选择 ModuleScript 。一个新模块脚本显示在 ServerStorage 下。你正在将模块脚本放置到 ServerStorage 中,因为你想管理服务器上的硬币收集逻辑。

    Studio's Explorer window with both the ServerScriptService's plus icon and ModuleScript object highlighted.
  3. 将模块脚本重命名为 PlayerData

    Studio's Explorer window with the PlayerData script highlighted under ServerStorage.
  4. 将默认代码替换为以下验证码:


    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_DATA
    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 表的数据。如果玩家尚未收集硬币,它将返回一个 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_DATA
    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 生成排行榜。

要创建排行榜:

  1. 探索器 窗口中,在 ServerStorage 中创建一个 ModuleScript ,然后将模块脚本重命名为 排行榜

    Studio's Explorer window with the Leaderboard script highlighted under ServerStorage.
  2. 将默认代码替换为以下验证码:


    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()排行榜 模块中唯一的公共函数。如果尚未存在,它会为指定的玩家或排行榜本身创建状态值。

    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

整合模块脚本

完成了 PlayerDataLeaderboard 模块脚本,需要在 CoinService 脚本中管理和显示玩家币数据。要更新 金币服务 :

  1. 浏览器 窗口中,打开 CoinService 脚本。

  2. 用以下代码替换现有代验证码:


    -- 初始化服务和变量
    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() 函数。
    • 宣言 COIN_AMOUNT_TO_ADD 作为玩家收集硬币时要添加的硬币数量,以及 COIN_KEY_NAME 作为在 PlayerData 中定义的关键名称。
    • 创建助助函数 updatePlayerCoins() 来更新玩家的硬币数量和相关排行榜统计数据
    • onCoinTouched() 中替换占位符 print() 声明以调用 updatePlayerCoins()

游戏测试

是时候看看硬币收集是否按预期运行了。当你触碰并收集游戏中的硬币时,你应该能够在排行榜 UI 上看到你收集的硬币数量。要测试您的体验:

  1. 在工具栏中,单击 播放 按钮。Studio 进入游戏测试模式。

    Play button highlighted in Studio's playtesting options.
  2. 将角色移动到触碰硬币。如果你的脚本正常运行,排行榜 UI 会显示并增加你收集更多硬币时的硬币数量。