Hello! I’m currently working on a game where I have a LOT of values I’d like to save whenever the player leaves/joins the game.
The values simply don’t save/load properly.
I’ve tried so many different scripts that just don’t work, and I’ve done a lot of research. But for some reason it won’t work. For some scripts it saves them but doesn’t load properly. With some it doesn’t even save. I’ve been having this issue for more than a year without a save system, but it’s about time I get one but I can’t get it right.
Whenever the server starts, it makes a folder in ReplicatedStorage called “PlayerFolders”. Then, whenever a player joins the game, it makes a folder inside of PlayerFolders with their username. Inside of the usernames folder it has a lot of different values such as “Currency”. I’d like to save all of these values whenever the player leaves the game, then load them in again whenever they join back.
I do not currently have a “set” script, just the default one that makes the values.
local RP = game:GetService(“ReplicatedStorage”)
local Folder = Instance.new(“Folder”)
Folder.Parent = RP
Folder.Name = “PlayerFolders”
game.Players.PlayerAdded:Connect(function(Player)
if game.ReplicatedStorage.PlayerFolders:FindFirstChild(Player.Name) then
else
local PlayerFolder = Instance.new("Folder")
PlayerFolder.Parent = Folder
PlayerFolder.Name = Player.Name
local Currency = Instance.new("NumberValue")
Currency.Parent = PlayerFolder
Currency.Name = "Currency"
Currency.Value = 2000
local FireDefense = Instance.new("NumberValue")
FireDefense.Parent = PlayerFolder
FireDefense.Name = "FireDefense"
FireDefense.Value = 1
local FireDamageTaken = Instance.new("NumberValue")
FireDamageTaken.Parent = PlayerFolder
FireDamageTaken.Name = "FireDamageTaken"
FireDamageTaken.Value = 0
local TimedMeditating = Instance.new("NumberValue")
TimedMeditating.Parent = PlayerFolder
TimedMeditating.Name = "TimedMeditating"
TimedMeditating.Value = 0
end
end)
I know that I’m not supposed to ask for code, but again I’ve tried a lot of different approaches and scripts that just don’t work, so I’d really appreciate some help.
I have tried to use datastores with a bunch of different scripts, but again they don’t work. I don’t have a specific example, but it doesn’t load once it’s been saved.
Ok, I can provide an easier example. Let’s say you had “Coins” as a value. Here is how you would load and save it:
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("MainData")
game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local data = dss:GetAsync(plr.UserId) --get player's saved data
local Coins = Instance.new("NumberValue")
Coins.Name = "Coins"
Coins.Value = data or 0 --set to 0 if there is no data, else use saved data
Coins.Parent = leaderstats
end)
game.Players.PlayerRemoving:Connect(function(plr) --when player is leaving
ds:SetAsync(plr.UserId, plr.leaderstats.Coins.Value) --save the player's data
end)
game:BindToClose(function() --to save data when game closes
for i,plr in pairs(game.Players:GetPlayers()) do --go through all players
ds:SetAsync(plr.UserId, plr.leaderstats.Coins.Value) --save the player's data
end
end)
I changed up the script a little bit to match where I hold the values, but I am getting this error.:
GetAsync is not a valid member of DataStoreService “DataStoreService”, Line 12
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("MainData")
local RP = game:GetService("ReplicatedStorage")
local Folder = Instance.new("Folder")
Folder.Parent = RP
Folder.Name = "PlayerFolders"
game.Players.PlayerAdded:Connect(function(Player)
local data = dss:GetAsync(Player.UserId)
local PlayerFolder = Instance.new("Folder")
PlayerFolder.Parent = Folder
PlayerFolder.Name = Player.Name
local Currency = Instance.new("NumberValue")
Currency.Parent = PlayerFolder
Currency.Name = "Currency"
Currency.Value = data or 2000
end)
game.Players.PlayerRemoving:Connect(function(Player)
ds:SetAsync(Player.UserId, Folder:FindFirstChild(Player.Name).Currency.Value)
end)
game:BindToClose(function()
for i,Player in pairs(game.Players:GetPlayers()) do
ds:SetAsync(Player.UserId, Folder:FindFirstChild(Player.Name).Currency.Value)
end
end)
Also, with the script I have right now (Basically what you gave me but I just have the new FireDefense, both of the values are now the same, when they are supposed to be different.
For multiple values, I would put them into a table. Using “Coins” and “Money” as a reference, this is what it would look like:
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("MainData")
game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local data = dss:GetAsync(plr.UserId) or {} --get player's saved data
local Coins = Instance.new("NumberValue")
Coins.Name = "Coins"
Coins.Value = data.Coins or 0 --set to 0 if there is no data, else use saved data
Coins.Parent = leaderstats
local Money = Instance.new("NumberValue")
Money.Name = "Money"
Money.Value = data.Money or 0
Money.Parent = leaderstats
end)
game.Players.PlayerRemoving:Connect(function(plr) --when player is leaving
ds:SetAsync(plr.UserId, {
Coins = plr.leaderstats.Coins.Value,
Money = plr.leaderstats.Money.Value
}) --save the player's data
end)
game:BindToClose(function() --to save data when game closes
for i,plr in pairs(game.Players:GetPlayers()) do --go through all players
ds:SetAsync(plr.UserId, {
Coins = plr.leaderstats.Coins.Value,
Money = plr.leaderstats.Money.Value
}) --save the player's data
end
end)
I made the changes to match the game, but now both values are 0 whenever you join the game. The code:
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("MainData")
local RP = game:GetService("ReplicatedStorage")
local Folder = Instance.new("Folder")
Folder.Parent = RP
Folder.Name = "PlayerFolders"
game.Players.PlayerAdded:Connect(function(Player)
local data = ds:GetAsync(Player.UserId) or {}
local PlayerFolder = Instance.new("Folder")
PlayerFolder.Parent = Folder
PlayerFolder.Name = Player.Name
local Currency = Instance.new("NumberValue")
Currency.Parent = PlayerFolder
Currency.Name = "Currency"
Currency.Value = data or 2000
local FireDefense = Instance.new("NumberValue")
FireDefense.Parent = PlayerFolder
FireDefense.Name = "FireDefense"
FireDefense.Value = data or 1
end)
game.Players.PlayerRemoving:Connect(function(Player)
ds:SetAsync(Player.UserId, {
Currency = Folder:FindFirstChild(Player.Name).Currency.Value,
FireDefense = Folder:FindFirstChild(Player.Name).FireDefense.Value
})
end)
game:BindToClose(function()
for i,Player in pairs(game.Players:GetPlayers()) do
ds:SetAsync(Player.UserId, {
Currency = Folder:FindFirstChild(Player.Name).Currency.Value,
FireDefense = Folder:FindFirstChild(Player.Name).FireDefense.Value
})
end
end)
I change the values in the server. For example, if I change the currency to 200, if you join it is 0.
For anybody reading this in the future, just make sure to always get/save data in a pcall. Without a pcall, if the data saving/recieving fails, it will throw an error and stop data saving entirely.
It should look like this when you are saving/recieving data:
--Recieving data
local data
local success, err = pcall(function()
data = datastore:GetAsync(UserId)
end)
if not success then
warn(err)
end
--Saving Data
local success, err = pcall(function()
datastore:SetAsync(UserId, dataToSave)
end)
if not success then
warn(err)
end