What do you want to achieve?
I want to save player data in my game, - clicks, gems, rebirths and multiplier -, so that players can continue from where they left off when they rejoin the game.
What is the issue?
I have written a script to save player data, but it is only saving the gems and not the rest of the values. I am not sure what the issue is and I have tried a few solutions without success.
What solutions have you tried so far?
I have checked the script for any obvious errors, and I have also looked for solutions on the Developer Hub, but I have not found anything that solves my problem. I have also tried modifying the script to include the clicks, rebirths and multipliers values in the data table that is being saved, but it still only saves the gems value.
The script here:
local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("data")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local clicks = Instance.new("IntValue")
clicks.Name = "Clicks"
clicks.Parent = leaderstats
local gems = Instance.new("IntValue")
gems.Name = "Gems"
gems.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Parent = leaderstats
local multiplier = Instance.new("IntValue")
multiplier.Name = "Multiplier"
multiplier.Parent = player
local data = {}
local success, errormessage = pcall(function()
data = dataStore:GetAsync(player.UserId.."-data") or {}
end)
if success then
clicks.Value = data.clicks or 0
gems.Value = data.gems or 0
rebirths.Value = data.rebirths or 0
multiplier.Value = data.multiplier or 0
else
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local currentPlayer = game.Players:GetPlayerByUserId(player.UserId)
local success, errormessage = pcall(function()
local data = {
clicks = currentPlayer.leaderstats.Clicks.Value,
gems = currentPlayer.leaderstats.Gems.Value,
rebirths = currentPlayer.leaderstats.Rebirths.Value,
multiplier = currentPlayer.Multiplier.Value,
}
dataStore:SetAsync(player.UserId.."-data", data)
end)
if not success then
warn(errormessage)
end
end)
game.ReplicatedStorage.RebirthEvent.OnServerEvent:Connect(function(player)
local leaderstats = player.leaderstats
local multiplier = player.Multiplier
leaderstats.Clicks.Value = 0
leaderstats.Rebirths.Value += 1
multiplier.Value += 2
end)
game:BindToClose(function()
wait(3)
end)
An easy way to see what the values are is to print what they are when the player leaves. This would tell you if the values aren’t being calculated properly before the player leaves.
BindToClose will fire this code when the Server closes, In Studio, The game will fire this callback, and then close, so in this case, it will yield for roughly 3 seconds, and then close.
I ran into a similar issue with local scripts as you can do it your method you have to re-state that player.leaderstats.Rebirths.Value = (whatever local value you made up). Because in a sense that value is stored locally. Also it looks like you watched CodeGnome, as its very similar to my first database script, but you did not set the data of the session.
For example when you have a datastore and you make changes with local variables leaderstats never changes a thing, I found this out because I didn’t watch his video all the way through haha.
Here is an example:
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local database = DataStoreService:GetDataStore("playerDatastore")
local sessionData = {}
function PlayerAdded(Player)
--Leaderstats
local leaderstats = Instance.new("Folder", Player)
leaderstats.Name = "leaderstats"
local Gold = Instance.new("IntValue", leaderstats)
Gold.Name = "Gold"
Gold.Parent = leaderstats
local success = nil
local playerData = nil
local attempt = 1
repeat
success, playerData = pcall(function()
return database:GetAsync(Player.UserId)
end)
attempt += 1
if not success then
warn (playerData)
task.wait(3)
end
until success or attempt == 5
if success then
print("Connected to database")
if not playerData then
print("Assigning default data")
playerData = {
["Gold"] = 5,
-- put your stats here
}
end
-- here is where I feel like you aren't setting the values stored in the table BACK into the table.
sessionData[Player.UserId] = playerData
else
warn("Unable to get data for", Player.UserId)
Player:Kick("Unable to load your data. Try again later")
end
for i, val in pairs(playerData) do
print(val)
end
Gold.Value = sessionData[Player.UserId].Gold
Gold.Changed:Connect(function()
sessionData[Player.UserId].Gold = Gold.Value
end)
What your code does when I read it is it just simply changes the variables, prints it changed them, but never went back and set the values again. I hope this helps as your code is very nice and I just feel you left out that little bit. CodeGnome made a video on this for reference and I take zero credit for the code above. Also do not copy and paste that code, as it is not the complete database script. It will not work.
I realized that the problem with my code wasn’t related to the datastore. Although your suggestions helped improve my datastore implementation, the code was still only saving the one value. Upon further investigation, I discovered that local scripts were the cause of the issue. As local scripts only run on the client, they don’t replicate any changes made to the leaderstats values to the server. To fix this, I edited my local scripts a bit and used RemoteEvents, which allowed it to update the leaderstats values and save them to the datastore from the server. Overall, your suggestions and some additional troubleshooting helped me find a solution to my problem. Thank you for your help!