_G List is not saved

I create a list with _G and add variables to this list, then I add a value to these variables and try to save this value, but the value is not saved. What is the reason?

local DataStoreService = game:GetService("DataStoreService") 
local playerDataStore = DataStoreService:GetDataStore("PlayerData")
local function getPlayerData(player)
    local success, data = pcall(function() 
        return playerDataStore:GetAsync(player.UserId)
    end)
    if success and data then
        return data
    else
        return nil
    end
end


game.Players.PlayerAdded:Connect(function(player)
    local data = getPlayerData(player)

    _G.PlayerCrowns = {}
    for i = 1, 35 do
        if not _G.PlayerCrowns[player] then
            _G.PlayerCrowns[player] = {}
        end
        _G.PlayerCrowns[player]["Crown" .. i] = {Name = "Crown" .. i, Value = 0}
    end

    if data then
        print("Player has data")
        for i = 1,35 do
            print(data.Crowns["Crown"..i].Value)
            _G.PlayerCrowns[player]["Crown"..i].Value = data.Crowns["Crown"..i].Value
        end 
    else
        print("Player hasn't data")
        for _, Crown in ipairs(_G.PlayerCrowns[player]) do
            Crown.Value = 0
        end
    end

    game.Players.PlayerRemoving:Connect(function(player)
        local success, err = pcall(function()
            local DataList = {
                Crowns = _G.PlayerCrowns[player],
            }
            playerDataStore:SetAsync(player.UserId, DataList)
        end)
        
        if not success then
            warn("Failed to save data for player " .. player.Name .. ": " .. err)
        end
    end)
end)
3 Likes

Every time a player joins you’re redefining _G.PlayerCrowns as a new table, which clears the table of previous entries.

You should create this table outside of that event since you want it to persist and hold information relating to all clients.

i.e.

_G.PlayerCrowns = { }

game.Players.PlayerAdded:Connect(function (player)
  -- stuff
end)
1 Like

This is true, but it has no effect on whether the data is saved or not.

1 Like

Does this issue occur in Studio or in game?

1 Like

The same problem occurs in both.

1 Like

Oh your issue is with DataStoreService not saving, not that the global environment is redefined?

I would second the question below - the value wouldn’t be saved in the case of an unpublished game as described here:


Otherwise, are you getting any errors returned from the pcall?

Any debug-related information you could provide would also be handy, e.g. have you confirmed the events are firing? Have you printed the expected value before saving, or logged the value when loading?

Will need a little more information than the OP, esp. as it’s not something than can be quickly replicated on our machines without setting up a test place and publishing it.

1 Like

I was asking because from Studio it usually doesn’t save unless you use:

game:BindToClose()

Also, I would put the: game.Players.PlayerRemoving event outside the game.Players.PlayerAdded, probably unrelated to your issue.

Yes, I published my game. I was already using the data store for this game. Also I don’t have a lot of information about BindToClose, can you help me with that?

No, I’m not getting any errors.I tested whether the code works using the print function, and the code works, but data is sometimes saved, sometimes not but mostly not saved.

I also changed my code a bit.

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

local function getPlayerData(player)
    local success, data = pcall(function()
        return playerDataStore:GetAsync(tostring(player.UserId))
    end)

    if success and data then
        return data
    else
        return nil
    end
end

_G.PlayerCrowns = {}

game.Players.PlayerAdded:Connect(function(player)
    if not _G.PlayerCrowns[player] then
        _G.PlayerCrowns[player] = {}
    end

    local data = getPlayerData(player)

    for i = 1, 35 do
        _G.PlayerCrowns[player]["Crown" .. i] = _G.PlayerCrowns[player]["Crown" .. i] or {Name = "Crown" .. i, Value = 0}
    end

    if data then
        print("Player has data")
        for i = 1, 35 do
            _G.PlayerCrowns[player]["Crown" .. i].Value = data["Crown" .. i] or 0
        end
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    local success, err = pcall(function()
        local DataList = {}
        for i = 1, 35 do
            table.insert(DataList, {["Crown" .. i] = _G.PlayerCrowns[player]["Crown" .. i].Value})
        end
        playerDataStore:SetAsync(tostring(player.UserId), DataList)
    end)

    if not success then
        warn("Failed to save data for player " .. player.Name .. ": " .. err)
    end
end)

Oh I’ve just realised your issue.

When you’re saving the values, you’re doing the following:

local DataList = {}
for i = 1, 35 do
    table.insert(DataList, {["Crown" .. i] = _G.PlayerCrowns[player]["Crown" .. i].Value})
end

This means that the DataList table would look something similar to this:

[
  {"Crown1": 0},
  {"Crown2": 0},
  {"Crown3": 0}
]

…but, when reading it from the DataStoreService, you’re trying to read the data as though you saved the DataList like this:

{
  "Crown1": 0,
  "Crown2": 0,
  "Crown3": 0
}

You either need to change how you read the value from the datastore, or you need to change how you save it.

If you were to do the latter, you should be saving the data in a manner similar to the following:

local DataList = {}
for i = 1, 35 do
    DataList['Crown' .. i] = _G.PlayerCrowns[player]["Crown" .. i].Value
end
2 Likes

I did what you said but there was no change. I don’t think that’s the problem, because sometimes it saves the data and sometimes it doesn’t. I can somehow solve the problem if it doesn’t save the data at all, but this is something different.

Edit:
Also, the code you gave seems a little wrong because when I type this code, I get “nill” output. So I switched to the “Insert” command that I first used. print(data["Crown1"])

Edit2:
I figured out the reason why I was getting “nill” output, so I started using the command you wrote again.

I think the problem is in this code. Because I added some printing commands and I cannot get output from these commands. This indicates something is wrong. I wrote the entire code below. I’m outputting “a” for the PlayerRemoving function, then I’m outputting “x” from the getPlayerdata(player) command, but I’m not outputting “b” and “c”. Also, I cannot get the “y” output from the getPlayerdata command. So when we run the getPlayerdata function something goes wrong. Since I cannot get the “b” output, the lines of code where the data is saved do not work either. It’s not that it doesn’t actually work; The getPlayerdata function prevents Studio from reading the save data code. This will cause the data not to be saved.

Important Edit

I noticed something very important. If I enter the game and exit after 1 or 2 seconds, my data is saved and I get all the outputs. But I don’t know why my data is saved this way.

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

local function getPlayerData(player)
    local success, data = pcall(function() 
        print("x")
        return playerDataStore:GetAsync(tostring(player.UserId))
    end)
    print("y")
    if success and data then
        print("getPlayerData: Data retrieved successfully")
        return data
    else
        print("getPlayerData: Failed to retrieve data")
        return nil
    end
end

_G.PlayerCrowns = {}
local data

game.Players.PlayerAdded:Connect(function(player)
    if not _G.PlayerCrowns[player] then
        _G.PlayerCrowns[player] = {}
    end

    data = getPlayerData(player)

    for i = 1, 35 do
        _G.PlayerCrowns[player]["Crown" .. i] = _G.PlayerCrowns[player]["Crown" .. i] or {Name = "Crown" .. i, Value = 0}
    end

    if data then
        print("Player has data")
        for i, datatable in pairs(data) do
            print(datatable.Value,datatable.Name)
            _G.PlayerCrowns[player][datatable.Name].Value = datatable.Value
        end
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    print("a")
    data = getPlayerData(player)
    print("b")
    local success, err = pcall(function()
        local DataList = {}
        print("c")
        for key, value in pairs(data) do
            DataList[key] = {Name = key, Value = _G.PlayerCrowns[player][key].Value}
        end

        print(DataList["Crown1"].Value)
        playerDataStore:SetAsync(tostring(player.UserId), DataList)
    end)

    if not success then
        warn("Failed to save data for player " .. player.Name .. ": " .. err)
    end
end)