I have inserted your script into a blank baseplate, it works perfectly. Could it be that the server is closing before all the data is saved? I would read this article and try using it to see if your data saves afterward.
I had the same as well
but i recommend switching to DataStore2 if u dont want complexity but if u want tho ill give you a chance
lets say u have coins in your leaderstats
lets add bindtoclose
local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("myDataStore")
local players = game:GetService("Players")
local plrsLeft = 0
player.PlayerAdded:Connect(function(player)
plrsLeft = plrsLeft + 1
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = leaderstats
local success, errormessage = pcall(function()
myDataStore:GetAsync(player.UserId) -- No need for "User-"
end)
-- if it was success then run this
if success then
Coins = success[1] -- Means they are stored in the first table
else
warn("Error Failed to receive")
end
-- auto save (optional)
while wait(30) do
myDataStore:UpdateAsync(player.UserId, {Coins.Value} -- in this table is where u want to save)
end
end)
local BindEvent = Instance.new("BindableEvent")
player.PlayerRemoving:Connect(function(player)
plrsLeft = plrsLeft - 1
pcall(function()
myDataStore:UpdateAsync(player.UserId, {player.leaderstats.Coins.Value})
BindEvent:Fire()
end
end)
game:BindToClose(function()
while plrsLeft > 0 do
BindEvent.Event:Wait()
end
end
Never use SetAsync because it sets the value
But UpdateAsync reconsiders the old value before making changes
and bindable events to prevent data loss
I would recommend properly indenting your code for readability and it is also a good practice to indent your code.
i cant use studio rn so i used dev forum code
That’s not how UpdateAsync works. The problem with telling people blindly to use UpdateAsync over SetAsync without actually explaining the benefits is that you get code like this. UpdateAsync’s second argument is a transformation function that takes the old data that’s saved as an argument. For something like Coins, where the value may go up or down throughout a play-session, it’s much harder to sanity-check the old value to make sure what you’re saving makes sense.
Saying “never” is also not particularly helpful, as there are absolutely times you may want to completely overwrite data. I’d recommend reading this post where I give some example situations of when UpdateAsync should be used.
Pcall can return values. It is generlaly better practice to return the result from GetAsync()
rather than assining the result to a variable outside the pcall. This is what you should do when you are using GetAsync()
with pcall:
local Success, Result = pcall(function()
return DataStore:GetAsync(tostring(Player.UserId))
end)
The reason why you are getting this error is because I am assuming you made a small typo with player.PlayerAdded
. player
should be changed to players
. This is what the line should be:
players.PlayerAdded:Connect(function(player)
Instead of using SetAsync()
when saving data you should use UpdateAsync()
because according to the developers hub it is more reliable. Also according to to the developers hub it states using SetAsync()
can be hazardous because it forces the save onto the key without taking into account previously saved data. You should read over this community tutorial because it explains why and how you should use UpdateAsync():
Other than that I can’t see anything else wrong with your script other than changing how you use pcall. The code below should work perfectly fine because I have tested it and it works:
local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("myDataStore")
local players = game:GetService("Players")
players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = leaderstats
local success, data = pcall(function()
return myDataStore:GetAsync(tostring(player.UserId))
end)
if success then
cash.Value = data
else
print("There was an error whilst getting your data.")
warn(data)
end
end)
players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
myDataStore:UpdateAsync(tostring(player.UserId), function(OldData)
return player.leaderstats.Coins.Value
end)
end)
if success then
print("Player data successfully saved!")
else
print("There was an error saviing data.")
warn(errormessage)
end
end)
If you are changing your coins on the client it wont replicate to the server. This means when the server saves the data it will assume you haven’t changed the coins so it will save the default value. To fix this you should always update players leaderstats values on the server.
Is there a way to make leaderstat saving, without having to wait so much time?
Just change the 30 in while wait(30) do
assuming you are using FerbZides’s code. I do not recommend changing it though due to limits. Otherwise, I do not know what you mean by without having to wait so much time,
so if you mean something else please explain.
By using FerbZide’s code, I am getting this output:
[09:52:22.916 - ServerScriptService.myDataStore:33: Expected ')' (to close '(' at line 30), got 'end']
Well then, put an )
after the end I assume that something wasn’t closed off.
I have, I am getting this output:
09:59:02.927 - ServerScriptService.myDataStore:30: Expected ')' (to close '(' at line 28), got 'end'
. Yet It’s been closed off?
One moment as I put the code into studio and fix the indenting for you and then see what’s wrong.
Little off-topic here, but I’m having some trouble with another script. I have a tool, when you equip it, and you click it’ll add points to the leaderboard. But it’s not working as it should. Here’s that script:
script.Parent.Activated:Connect(function()
local plr = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
plr.leaderstats.Coins.Value = plr.leaderstats.Coins.Value +3
end)
I have formatted the code and fixed all possible errors.
local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("myDataStore")
local players = game:GetService("Players")
local plrsLeft = 0
players.PlayerAdded:Connect(function(player)
plrsLeft = plrsLeft + 1
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = leaderstats
local success1,response1 = pcall(myDataStore.GetAsync,myDataStore,player.UserId)
if success1 then
cash.Value = response1
else
warn(response1)
end
while true do
wait(30)
local success2,response2 = pcall(myDataStore.UpdateAsync,myDataStore,player.UserId,function(oldValue)
return cash.Value
end)
if not success2 then
warn(response2)
end
end
end)
local BindEvent = Instance.new("BindableEvent")
players.PlayerRemoving:Connect(function(player)
plrsLeft = plrsLeft - 1
local success,response = pcall(myDataStore.UpdateAsync,myDataStore,player.UserId,function(oldValue)
return player.leaderstats.Coins.Value
end)
if success then
BindEvent:Fire()
else
warn(response)
end
end)
game:BindToClose(function()
while plrsLeft > 0 do
BindEvent.Event:Wait()
end
end)
You’re welcome! Also, there may be bits and pieces missing that I did not include but you can always modify the code.
It works perfectly for me, is your script a child of the tool? Is this a server script? Have you tried putting a print right after the event is fired? Also, I would recommend putting in a debounce to prevent someone just autoclicking to get a million coins instantly.
Also, In the code:
local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("myDataStore")
local players = game:GetService("Players")
local plrsLeft = 0
players.PlayerAdded:Connect(function(player)
plrsLeft = plrsLeft + 1
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = leaderstats
local success1,response1 = pcall(myDataStore.GetAsync,myDataStore,player.UserId)
if success1 then
cash.Value = response1
else
warn(response1)
end
while true do
wait(30)
local success2,response2 = pcall(myDataStore.UpdateAsync,myDataStore,player.UserId,function(oldValue)
return cash.Value
end)
if not success2 then
warn(response2)
end
end
end)
local BindEvent = Instance.new("BindableEvent")
players.PlayerRemoving:Connect(function(player)
plrsLeft = plrsLeft - 1
local success,response = pcall(myDataStore.UpdateAsync,myDataStore,player.UserId,function(oldValue)
return player.leaderstats.Coins.Value
end)
if success then
BindEvent:Fire()
else
warn(response)
end
end)
game:BindToClose(function()
while plrsLeft > 0 do
BindEvent.Event:Wait()
end
end) - Where does the leaderstats end and begin? I have a leaderstats script, and I believe by making one in this script It's messing with the tool script.
The script you posted above (post 24) should work with that script if everything is spelled correctly.
Hm, referring back to my original script… Everything works fine, if I alter the script, everything doesn’t work as needed.
Weird, make sure the paths are correct.
Adding onto my previous post, everything works with my original script, except for the data store script.