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

Roblox Studio中DataStore保存已购升级列表的问题排查

问题解决:DataStore加载玩家已购升级数据为空的问题

问题描述

我在游戏里做了本地记录已购升级名称的列表,防止玩家重复购买,但玩家退出游戏后列表会清空。我想把这个列表传到服务端存到DataStore,让玩家重新加入时能保留记录。现在代码里会话数据打印都正常,但重新加入时数据为空,只会加载默认值,求解决。

原代码

local DataStoreService = game:GetService("DataStoreService")
local upgradeDataStore = DataStoreService:GetDataStore("ClickerUpgra")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local recieveUpgradeNameEvent = ReplicatedStorage.ShopEvents.SendUpgradeName
local sessionPlayerData = {} --this is the dictionary you add all of the data to



local function SavePlayerData(userId,data)
    --function used to save player data
    local success, errorMessage = pcall(function()
        print("Success on saving that data ")
        
        upgradeDataStore:SetAsync(userId, data)
    end)
    if not success then
        
        print(errorMessage)
    end
end

local function LoadPlayerData(userId)
    --acceses player data from data store 
    local success, errorMessage = pcall(function()
        return upgradeDataStore:GetAsync(userId)
    end)
    if not success then
        print(errorMessage)
    end
end

recieveUpgradeNameEvent.OnServerEvent:Connect(function(player, UpgradeName)
    print("Recieved da event!!!")
    print(player)
    print(UpgradeName)
    table.insert(sessionPlayerData[player.UserId], UpgradeName)
    print(sessionPlayerData[player.UserId])
end)

game.Players.PlayerAdded:Connect(function(player)
    local data = LoadPlayerData(player.UserId)
    if data then
        sessionPlayerData[player.UserId] = data
        print("A player has data and is being set to them right now")
    else
        sessionPlayerData[player.UserId] = {} -- an empty table
        print("Assigning default values")
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    print("Trying to save data my guy")
    print(sessionPlayerData[player.UserId])
    SavePlayerData(player.UserId, sessionPlayerData[player.UserId])
end)

问题分析与修复方案

核心问题1:LoadPlayerData函数未返回获取到的数据

原函数中,即便pcall成功从DataStore拿到数据,也没有将数据返回,导致PlayerAdded事件里的data永远为nil,只能走默认值分支。

核心问题2:SavePlayerData的成功提示逻辑错误

原代码在pcall内部先打印成功提示,但这个操作不会判断SetAsync是否真的执行成功,应该把提示放到success为true的分支里。

其他优化点

  • DataStore名称ClickerUpgra疑似拼写不完整(比如应为ClickerUpgrades),虽不影响功能,但建议修正避免后续混淆。
  • 给LoadPlayerData添加默认返回值,确保获取失败或无数据时也能返回空表,避免后续逻辑报错。

修复后的代码

local DataStoreService = game:GetService("DataStoreService")
-- 修正DataStore名称(可选,按需调整)
local upgradeDataStore = DataStoreService:GetDataStore("ClickerUpgrades")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local recieveUpgradeNameEvent = ReplicatedStorage.ShopEvents.SendUpgradeName
local sessionPlayerData = {}

local function SavePlayerData(userId, data)
    local success, errorMessage = pcall(function()
        upgradeDataStore:SetAsync(userId, data)
    end)
    if success then
        print(string.format("成功保存玩家 %d 的数据", userId))
    else
        print(string.format("保存玩家 %d 数据失败: %s", userId, errorMessage))
    end
end

local function LoadPlayerData(userId)
    local success, result = pcall(function()
        return upgradeDataStore:GetAsync(userId)
    end)
    if success then
        -- 无数据时返回空表作为默认值
        return result or {}
    else
        print(string.format("加载玩家 %d 数据失败: %s", userId, result))
        -- 加载失败时返回空表
        return {}
    end
end

recieveUpgradeNameEvent.OnServerEvent:Connect(function(player, UpgradeName)
    print("收到升级购买事件!")
    print(player.Name, UpgradeName)
    -- 确保会话数据存在,避免nil索引错误
    local playerData = sessionPlayerData[player.UserId]
    if playerData then
        table.insert(playerData, UpgradeName)
        print("当前已购升级列表:", playerData)
    end
end)

game.Players.PlayerAdded:Connect(function(player)
    local data = LoadPlayerData(player.UserId)
    sessionPlayerData[player.UserId] = data
    if #data > 0 then
        print(string.format("玩家 %s 已加载已购升级记录", player.Name))
    else
        print(string.format("玩家 %s 无已购记录,初始化空列表", player.Name))
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    local userId = player.UserId
    print(string.format("开始保存玩家 %s 的数据", player.Name))
    print("待保存的已购升级列表:", sessionPlayerData[userId])
    SavePlayerData(userId, sessionPlayerData[userId])
    -- 清除会话数据,释放内存
    sessionPlayerData[userId] = nil
end)

额外注意事项

  • 测试DataStore时,需在Roblox Studio中开启启用Studio访问API服务(设置→游戏设置→安全→启用Studio访问API服务)。
  • DataStore有请求限制,高并发场景建议使用UpdateAsync或添加重试逻辑,避免触发限流。
  • 可考虑用字典存储升级名称(以名称为键),比数组更高效判断是否已购买,防止重复插入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:53:17