You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roblox DataStore无法保存数据且无法识别UserId,等级系统运行异常

修复方案

核心问题说明

  • 大小写敏感问题:Roblox 实例属性严格区分大小写,你在create_table函数中使用的stat.name、stat.value为错误写法,正确属性名为Name、Value。小写写法会读取到空值,导致每次保存的玩家数据为空,触发加载逻辑的初始值重置,这就是数据无法保存、数值大于0就失效的根本原因。
  • 界面更新逻辑错误:game.StarterGui是界面模板容器,修改其内容不会同步到当前在线玩家的显示界面,还会影响所有后续加入的玩家,应该修改对应用户PlayerGui下的界面元素。
  • 额外注意:Studio 测试前需要在「游戏设置→安全」中开启「允许 Studio 访问 API 服务」,否则 DataStore 不会生效。

修复后代码

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")

local function onPlayerJoin(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "lead"
    leaderstats.Parent = player
    
    local xp = Instance.new("IntValue", leaderstats)
    xp.Name = "Exp"
    
    local level = Instance.new("IntValue", leaderstats)
    level.Name = "Level"
    
    local maxExp = Instance.new("IntValue", leaderstats)
    maxExp.Name = "Max"
    
    local playerUserId = "Player_"..player.UserId -- 改成下划线避免特殊字符问题
    local success, data = pcall(function()
        return playerData:GetAsync(tostring(playerUserId))
    end)
    
    if success then
        if data then
            xp.Value = data['Exp']
            level.Value = data['Level']
            -- 按需求每级基础最大XP为1000,也可替换为读取存储的Max值
            maxExp.Value = (level.Value + 1) * 1000
            -- 正确更新当前玩家的界面
            local playerGui = player.PlayerGui
            playerGui.ScreenGui.One.Text = tostring(xp.Value)
            playerGui.ScreenGui.Two.Text = tostring(level.Value)
            playerGui.ScreenGui.Three.Text = tostring(maxExp.Value)
        else
            -- 新玩家初始值
            xp.Value = 0
            level.Value = 0
            maxExp.Value = 1000
            local playerGui = player.PlayerGui
            playerGui.ScreenGui.Three.Text = "Hi"
            print("first time join")
        end
    else
        warn("Failed to load data for "..player.Name)
        -- 加载失败给默认值避免报错
        xp.Value = 0
        level.Value = 0
        maxExp.Value = 1000
    end
end

local function create_table(player)
    local player_stats = {}
    for _, stat in pairs(player.lead:GetChildren()) do
        -- 修复属性大小写问题
        player_stats[stat.Name] = stat.Value
    end
    return player_stats
end

local function onPlayerExit(player)
    local player_stats = create_table(player)
    local success, err = pcall(function()
        local playerUserId = "Player_"..player.UserId
        playerData:SetAsync(tostring(playerUserId), player_stats)
    end)
    
    if not success then
        warn('Could not save data for '..player.Name..": "..err)
    end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)

-- Studio测试时加这段,解决测试时PlayerRemoving不触发的问题
game:BindToClose(function()
    for _, player in pairs(game.Players:GetPlayers()) do
        onPlayerExit(player)
    end
    task.wait(3) -- 给数据保存留缓冲时间
end)

内容的提问来源于stack exchange,提问作者Ragno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 18:15:03