为什么我在快速获得战利品后离开,这个 roblox 脚本就不能保存?

我制作了这个用于加载和保存数据的脚本。如果玩家很快就加入并退出,如何使它保存?如果我快速离开,它会丢弃数据?我尝试了几种方法,但似乎都不起作用。如果有人很快地加入,获得了很多赃物,然后退出,这将非常糟糕。有没有办法在关闭之前告诉服务器先保存所有东西呢?

local Database = game:GetService("DataStoreService"):GetDataStore("MAIN")
local RStorage = game:GetService("ReplicatedStorage")
local PlayerIndex = {}
local CanSaveData = true
local BFunctionF = Instance.new("Folder", RStorage)
function SaveData(Player)
    local SCS, Result = pcall(function()
        Database:SetAsync("USER"..Player.UserId, PlayerIndex[Player])
        while Database:GetAsync("USER"..Player.UserId) ~= PlayerIndex[Player] do
            Database:SetAsync("USER"..Player.UserId, PlayerIndex[Player])
            warn("Stupid")
        end
        CanSaveData = true
    end)
    if not SCS then
        warn(Result)
    end
end
BFunctionF.Name  = "DataManagerBindableFunctions"
game.Players.PlayerAdded:Connect(function(Player)
    local ChangeData = Instance.new("BindableFunction", BFunctionF)
    ChangeData.Name = Player.UserId

    local Stats = Instance.new("BoolValue", Player)
    Stats.Name = "leaderstats"

    local LevelStat = Instance.new("IntValue", Stats)
    LevelStat.Name = "等级"

    local CrystalStat = Instance.new("IntValue", Stats)
    CrystalStat.Name = "水晶"

    local MoneyStat = Instance.new("IntValue", Stats)
    MoneyStat.Name = "金钱"

    local SCS, Data = pcall(function()
        local RawData = Database:GetAsync("USER"..Player.UserId) or {}
        local NewData = {
            ['Level'] = RawData['Level'] or 0,
            ['LvlXP'] = RawData['LvlXP'] or 0,
            ['Money'] = RawData['Money'] or 0,
            ['Crystal'] = RawData['Crystal'] or 0,
            ['Bonker'] = RawData['Bonker'] or 0,
            ['Sword'] = RawData['Sword'] or 0,
            ['Hammer'] = RawData['Hammer'] or 0,
            ['Knife'] = RawData['Knife'] or 0,
            ['Brick'] = RawData['Brick'] or 0}
        return NewData
    end)

    if SCS and Data then
        PlayerIndex[Player] = Data
    end

    MoneyStat.Value = Data.Money
    LevelStat.Value = Data.Level
    CrystalStat.Value = Data.Crystal

    ChangeData.OnInvoke = function(Type, Amount)
        print(Player, Type, Data[Type])
        if Data[Type] == nil then
            warn("Fake Playerdata Type")
        else
            local NV = Data[Type]+Amount
            if Type == "Crystal" then
                CrystalStat.Value = NV
            elseif Type == "Money" then
                MoneyStat.Value = NV
            elseif Type == "Level" then
                LevelStat.Value = NV
            end
            Data[Type] = NV
        end
        print(Data[Type])
        return Data[Type]
    end
end)

game.Players.PlayerRemoving:Connect(function(Player)
    if CanSaveData then
        CanSaveData = false
        SaveData(Player)
    end
end)
game:BindToClose(function()
    for O, Player in pairs(game.Players:GetPlayers()) do
        if CanSaveData then
            CanSaveData = false
            SaveData(Player)
        end
    end
end)

我该如何解决这个问题呢?

点赞
用户6553328
用户6553328

我的建议是停止使用 Async 来保存玩家数据。比如,如果 GetAsync() 失败,那么玩家的数据可能会被设置为 false 或 nil。如果这个值被写入数据存储,那么玩家的数据将完全被覆盖。如果玩家在不同的服务器之间快速切换,GetAsync() 还可能检索到不正确的先前数据。为了防止这种情况,我们使用 UpdateAsync()

2020-11-23 17:31:03
用户15498710
用户15498710

你应该在 game:BindToClose() 函数的末尾添加 wait(10),以使游戏在停止前等待更长的时间,从而使其能够保存数据。(game:BindToClose() 的最大等待时间为30秒)

game:BindToClose(function()
    for O, Player in pairs(game.Players:GetPlayers()) do
        if CanSaveData then
            CanSaveData = false
            SaveData(Player)
        end
    end
    wait(10)
end)
2022-08-09 19:39:19