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

Roblox开发中leaderstats的DataStore数据无法保存问题

故障原因

你的代码存在多个直接导致数据存储失效的问题:

  • 未定义dataStoreService对象,脚本第一行直接调用未声明的变量会直接抛出运行时错误,后续所有逻辑都不会执行。
  • 新玩家首次进入游戏时,GetAsync查询不存在的键会返回nil,直接将nil赋值给IntValue.Value会触发类型错误,IntValue仅接受整数类型值。
  • PlayerRemoving事件中的SetAsync是异步网络请求,玩家离开时Roblox可能在请求发出前就回收脚本运行环境,导致保存请求被直接丢弃。
  • 没有请求失败重试逻辑,DataStore接口存在频率限制、网络波动等偶发失败场景,单次请求失败就会直接丢失本次存档。
  • 未处理服务器关闭场景:游戏服务器关停时所有玩家会同时触发离开,但此时服务已经进入停止流程,单独的PlayerRemoving监听大概率无法完成保存。
  • (常见配置问题)本地Studio测试时如果没开启API权限,所有DataStore请求会被直接拒绝。
修正后代码

把下面代码放到ServerScriptService下的服务端Script中(不要放到LocalScript或者StarterPlayerScripts里,客户端无DataStore调用权限):

-- 服务获取
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- 常量配置
local CLICK_DATA_STORE = DataStoreService:GetDataStore("clickDataStore")
local SAVE_RETRY_TIMES = 3 -- 失败重试次数
local DEFAULT_CLICKS = 0 -- 新玩家默认数据

-- 通用重试封装
local function safeRequest(requestFunc, ...)
    local success, result
    for i = 1, SAVE_RETRY_TIMES do
        success, result = pcall(requestFunc, ...)
        if success then
            return success, result
        end
        task.wait(1) -- 每次重试间隔1秒,避开频率限制
    end
    return success, result
end

Players.PlayerAdded:Connect(function(plr)
    -- 初始化leaderstats
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = plr

    local clicks = Instance.new("IntValue")
    clicks.Name = "Clicks"
    clicks.Parent = leaderstats

    -- 读取数据
    local dataKey = plr.UserId.."-clicks"
    local loadSuccess, clickData = safeRequest(function()
        return CLICK_DATA_STORE:GetAsync(dataKey)
    end)

    if loadSuccess then
        clicks.Value = clickData or DEFAULT_CLICKS -- 空数据给默认值
        print("玩家"..plr.Name.."数据加载完成,当前点击数:"..clicks.Value)
    else
        clicks.Value = DEFAULT_CLICKS
        warn("玩家"..plr.Name.."数据加载失败,使用默认值,错误信息:"..tostring(clickData))
    end
end)

-- 玩家离开保存逻辑
local function savePlayerData(plr)
    if not plr:FindFirstChild("leaderstats") or not plr.leaderstats:FindFirstChild("Clicks") then
        return
    end
    local dataKey = plr.UserId.."-clicks"
    local saveSuccess, err = safeRequest(function()
        CLICK_DATA_STORE:SetAsync(dataKey, plr.leaderstats.Clicks.Value)
    end)

    if saveSuccess then
        print("玩家"..plr.Name.."数据保存完成")
    else
        warn("玩家"..plr.Name.."数据保存失败,错误信息:"..tostring(err))
    end
end

Players.PlayerRemoving:Connect(savePlayerData)

-- 服务器关闭时全量保存
game:BindToClose(function()
    for _, plr in pairs(Players:GetPlayers()) do
        task.spawn(savePlayerData, plr) -- 协程并发保存,减少等待时间
    end
    task.wait(3) -- 预留3秒等待所有保存请求完成
end)
测试前置检查
  • 打开Roblox Studio的「游戏设置-安全」页,勾选Enable Studio Access to API Services,否则本地测试时所有DataStore请求会被拦截。
  • 确保脚本是服务端Script(图标为灰色脚本),放置在ServerScriptService目录下,客户端LocalScript没有调用DataStore的权限。
  • 不要短时间内高频触发数据读写,DataStore对单键、单服务器的请求频率有明确限制,超过限制会被限流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:54:18