There is many issues I can see within this script and I will try my best to explain them all.
Your PlayerRemoving function should not be inside the PlayerJoined Function and should be seperate.
You should be using pcall()'s to catch any issues if your are not able to receive the players data.
I highly recommend combining all your datastores into one by saving a table to one datastore instead.
Here is an example of a datastore I have created:
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("PlayerData")
local CreateLeaderstats = function(Player, Data)
-- Do leaderstats stuff.
print(Data.Coins) -- Example of new table system.
end
game.Players.PlayerAdded:Connect(function(Player)
local Attempts = 0
RequestData = function()
local Success, Data = pcall(function()
return DataStore:GetAsync(Player.UserId)
end)
if Success then
if Data then
-- They have previous saved data.
CreateLeaderstats(Player, Data)
else
--New player
local Data = {
["Coins"] = 100,
["Gems"] = 10,
--Etc
}
CreateLeaderstats(Player, Data)
end
else
if Attempts < 3 then -- If not able to get data try again.
Attempts = Attempts + 1
wait(5) -- To prevent datastore request dropping.
RequestData()
else
Player:Kick("Error loading data.")
end
end
end
RequestData()
end)
game.Players.PlayerRemoving:Connect(function(Player)
local Data = {
["Coins"] = Player.leaderstats.Coins.Value,
["Gems"] = Player.leaderstats.Gems.Value,
}
DataStore:SetAsync(Player.UserId, Data)
end)
Data loss is not too common, however not impossible.
I would recommend using ProfileService as it has excellent features, including session-locking (useful if you have a trading system as it prevents duplication and so on).
Regardless, I do suggest that you add a game:BindToClose() and save on an interval, ex. every 2-3 minutes.
You should also wrap your calls in a pcall (protected call) and handle errors when they occur.
The last thing I suggest is having everything inside a table, like this:
Not sure what you mean there. In what sense? This is the way you access the values of keys in a dictionary. Dictionaries are best practice for working with DataStores.