Hey, so recently I’ve been trying to make a leaderstats saver using datastore.
However, it’s not working. So I thought I better come here.
This is my code:
local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("myDataStore")
local players = game:GetService("Players")
player.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(myDataStore.GetAsync, myDataStore, player.UserId)
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(myDataStore.SetAsync, myDataStore, player.UserId, player.leaderstats.Coins.Value)
if success then
print("Player data successfully saved!")
else
print("There was an error saviing data.")
warn(errormessage)
end
end)
This is my current output: 23:29:27.079 - ServerScriptService.myDataStore:5: attempt to index nil with 'PlayerAdded'
He is perfectly fine doing it his way. I assume he read this article and learned that way of using pcalls. Also, pcall’s 2nd variable can return data if you are using a GET method.
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.
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
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.
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']