I’ve been using a leader stats script that I’ve made myself, but I’m currently having issues with the data saving. For some reason, my datastore’s decide if they want to save the data or not depending on how there feeling. Because my data has barely been saving recently, and I don’t know why…
There are no error’s, but here’s the script.
--\\ Datastores - Made By StarJ3M //--
local DataStoreService = game:GetService("DataStoreService") -- Datastore Service
local totalBricksData = DataStoreService:GetDataStore("totalBricks") -- The All-Time Bricks
local studData = DataStoreService:GetDataStore("studData") -- The Currency
local killSoundData = DataStoreService:GetDataStore("savedKillSound") -- The Kill Sound for the player
local playerItemData = DataStoreService:GetDataStore("playerItemData")
local shopItemData = DataStoreService:GetDataStore("shopItemData")
local shopOptionsRemote = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents"):WaitForChild("LoadShopOptions")
local shopItemCancelRemote = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents"):WaitForChild("shopItemCancelRemote")
local shopItemPromptRemote = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents"):WaitForChild("shopItemPrompt")
local shopModule = require(game:GetService("ReplicatedStorage"):WaitForChild("ShopModule"))
--\\ Functions //--
function AddComma(Data)
Data = tostring(Data)
return (((Data:reverse()):gsub("%d%d%d", "%1,")):reverse()):gsub("^,", "")
end
game.Players.PlayerAdded:Connect(function(player)
local killSound = Instance.new("Sound", player)
killSound.Name = "killSound"
killSound.Volume = 2
killSound.SoundId = game:GetService("ReplicatedStorage"):WaitForChild("KillSounds"):WaitForChild("default").SoundId
local items = shopModule.createOwnedData(player)
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local Studs = Instance.new("NumberValue", leaderstats) -- The Currency
Studs.Name = "Studs"
Studs.Value = 0
local Bricks = Instance.new("IntValue", leaderstats) -- The Bricks broken between matches
Bricks.Name = "Bricks"
Bricks.Value = 0
local totalBricks = Instance.new("IntValue", leaderstats) -- All time bricks broken
totalBricks.Name = "T. Bricks"
totalBricks.Value = 0
local brickData
local studsData
local itemsData
local possibleKillSound
local success, errorMessage = pcall(function()
brickData = totalBricksData:GetAsync(player.UserId)
studsData = studData:GetAsync(player.UserId)
possibleKillSound = killSoundData:GetAsync(player.UserId)
itemsData = playerItemData:GetAsync(player.UserId)
end)
if success then
totalBricks.Value = brickData
Studs.Value = studsData
killSound.SoundId = possibleKillSound
items = itemsData
elseif errorMessage then
warn(player.Name.."'s data cannot be found!..")
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local leaderstats = player.leaderstats
totalBricksData:SetAsync(player.UserId, leaderstats["T. Bricks"].Value)
studData:SetAsync(player.UserId, leaderstats.Studs.Value)
killSoundData:SetAsync(player.UserId, player.killSound.SoundId)
local playerItemTable
for i, v in pairs(shopModule.listOfPlayerItemTables) do
if v.ownerTag == player.Name then
playerItemTable = v
end
end
playerItemData:SetAsync(player.UserId, playerItemTable)
end)
As @AustnBlox stated, use the BindToClose, you are saving many Datastores when Studio is closing, is not having enough time to save everything.
Dont forget to wrap GetAsync and SetAsync on pcalls(), otherwise you wont be able to handle when Datastore saving or reading failed, certain APIs tends to fail due to connection issues, etc. You need a safe way to handle it by using pcall()
I agree totally with @OfficialPogCat, you should try to compress all possible data into only one DS. Sometimes you will need OrderedDatastores, which mandatory you will need to create a new one DS.
Hey @OfficialPogCat, actually I worked in a game that had around 6 datastores, servers of 25 players, and I never saw a datastore queuing due to many calls, or players losing its data… Im still struggling to understand the limits of DSS. Firstly I thought that its per DS, then I noticed the queuing warning was based per keys.
Plus, when a server shutdown has 30 seconds to finish the BindToClose functions.
And when dealing with releasing updates and shutdown servers I prefer to send a notification on player’s screen game is gonna be updated on X minutes, and the system will kick all players in all servers making sure its data is saved correctly.
Mmmh, still a little confusing to me, how the DSS limits exactly works…
I used the roblox documentation for this. I highly recommend checking it (though I am sure you have) as this was from roblox: https://create.roblox.com/docs/scripting/data/data-stores#limits. From reading it seems like a server wide limit, not each owns data store limit “Each server is allowed a certain number of data store requests based on the request type”
Intresting! To be fair you are only using half (ish) of the limit (310 allowed requests a minute, 150 used). For me I don’t like that as 30 seconds for 150 requests, with each request taking 6 seconds, are likely to have errors, or atleast, is a high risk of having them.
The real problem might be people that leave and rejoin though. If people often leave and rejoin you might reach that limit way too often because of that, but it would have to be many leave and rejoins, within the minute of a shutdown.
But again, would rather not take this risk when we can, which in this post looks like we can make it into one datastore
But, each request will not take 6 seconds. That cooldown is when rewritting the same key. If you save the key UserID1564647896 once, you should wait 6 seconds cooldown to rewrite that same key.
If the 25 players leaves the game at the same time, indeed are 150 request when having 6 datastores, but each SetAsync is independant to each other, so its not waiting 6 seconds to save the next one.
And yup, 150 is the half of the 310 request allowed per minute. So thats why theres no issues. And 30 seconds seems like enough time to do those 150 request, cause the cooldown is when rewritting the same key, not when saving on independant DSs
Yup. Are there is ways to handle that. Still sending 150 requests in 6 seconds sounds like a lot, and even with big games, Like pet simulator x, if they use 6 datastores, 30k players after an update shutdown, would be 180,000 requests within those 6 seconds. And I feel like I wouldn’t trust roblox enough to make sure each 180,000 requests are working in my experience.
But yes, I understand the cooldown isn’t per each request, but rather the time to save that data to a key in a datastore, and they are independant
Its a topic that after a couple of years here in Roblox I still dont understand it quite right haha…
Why in 6 seconds? Server would have 30 seconds to deal with the 150 requests on shutdown.
I dont think those being accumulative, are per server, if there is 25 players per server then 310 request per minute allowed. Having 6 datastores 150 request to be handled on 30 seconds, and not having a cooldown per saving request
I personally believe DataStore2 is simpler to use. As I don’t have as much experience using normal datastores, I cannot give you a solid answer regarding the :BindToClose.
You can use other datastores systems, and each system is different and each system might not require BindToClose()
However if you are looking at making a datastore using the default roblox method, BindToClose() should be used, as well as player removing. Just means that you have to handle everything yourself, instead of using another source like DataStrore2 / Profile service etc.
I am pretty sure @Dev_Peashie is saying that You should only make more then one data store, if you are using an OrderedDataStore. Not saying you should make one with the current data. OrderedDataStores is used to sort data, like with a global leaderboard system. From Roblox Documentation :
“By default, data stores do not sort their content, but sometimes it’s necessary to get data in an ordered fashion, such as persistent leaderboard stats” .
So Use a Normal Datastore, and Only 1 Datastore for your case, unless you are needing an OrderedDataStore
Have you also tried using a pcall() function to check for errors while saving playerdata? Additionally, if playerdata is saving too quickly, it will start to queue. During the queue, if a player leaves while their data is in queue, it will not save. You can try and prevent this by saving data more, or only when it changes.