Hello,
My data save is not working and my coroutine is not working.
Video showing scripts (at the end my studio crashes)
Video showing not saving:
Data script:
local datastore = game:GetService("DataStoreService")
local moneystore = datastore:GetDataStore("Stats")
game.Players.PlayerAdded:Connect(function(p)
local leader = Instance.new("IntValue",p)
leader.Name = "leaderstats"
local mon = Instance.new("NumberValue",leader)
mon.Name = "Money"
local so = Instance.new("StringValue",leader)
so.Name = "Job"
local ren = Instance.new("NumberValue",leader)
ren.Name = "Reputation"
local gor = moneystore:GetAsync(p.UserId)
if gor~=nil then
mon.Value = gor[1]
so.Value = gor[2]
ren.Value = gor[3]
else
gor = {mon.Value,so.Value,ren.Value}
end
for i,v in pairs(script.Notice:GetChildren()) do
local sog = v:Clone()
sog.Parent = p
end
end)
game.Players.PlayerRemoving:Connect(function(p)
moneystore:SetAsync(p.UserId,{p.leaderstats.Money.Value,p.leaderstats.Job.Value,p.leaderstats.Reputation.Value})
print('sag')
end)
local function save(v)
local a = coroutine.wrap(function()
moneystore:SetAsync(v.UserId,{v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value})
print('jiesh')
end)
end
game:BindToClose(function()
for i,v in pairs(game.Players:GetPlayers()) do
save(v)
end
end)
(Also side note here is that the change of the leaderstates values are server sided. Here is the remote event script for it.
game.ReplicatedStorage.AddRep.OnServerEvent:Connect(function(p,a,s)
a:Destroy()
for i,v in pairs(p:GetChildren()) do
print(v.Name)
end
p.leaderstats.Reputation.Value = p.leaderstats.Reputation.Value+math.floor(math.clamp(s,0,p.leaderstats.Money.Value)/5+0.5)
p.leaderstats.Money.Value = p.leaderstats.Money.Value-math.clamp(s,0,p.leaderstats.Money.Value)
end)
You should get an understanding of what scopes are:
The variable a is out of scope for the BindToClose Connection, therefore resulting in a nil.
But I don’t understand why you’re trying to do it like though, you can just do:
local function save(v)
coroutine.wrap(function()
moneystore:SetAsync(...) --Use pcalls for error handling btw.
end)()
end
game:BindToClose(function()
for _, client in pairs(game.Players:GetPlayers()) do
save(client)
end
end)
It sometimes works but not in a way that you might expect. It seems like the playerremoved works but the bindtoclose coroutine does not. (coroutine does not work at all)
As you can see, this is an unreliable and ineffective method to save data as it sometimes doesn’t work.
local datastore = game:GetService("DataStoreService")
local moneystore = datastore:GetDataStore("Stats")
game.Players.PlayerAdded:Connect(function(p)
local leader = Instance.new("IntValue",p)
leader.Name = "leaderstats"
local mon = Instance.new("NumberValue",leader)
mon.Name = "Money"
local so = Instance.new("StringValue",leader)
so.Name = "Job"
local ren = Instance.new("NumberValue",leader)
ren.Name = "Reputation"
local gor = moneystore:GetAsync(p.UserId)
if gor~=nil then
mon.Value = gor[1]
so.Value = gor[2]
ren.Value = gor[3]
else
gor = {mon.Value,so.Value,ren.Value}
end
for i,v in pairs(script.Notice:GetChildren()) do
local sog = v:Clone()
sog.Parent = p
end
end)
game.Players.PlayerRemoving:Connect(function(p)
moneystore:SetAsync(p.UserId,{p.leaderstats.Money.Value,p.leaderstats.Job.Value,p.leaderstats.Reputation.Value})
print('sag')
end)
local function save(v)
coroutine.wrap(function()
moneystore:SetAsync(v.UserId,{v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value})
print('jiesh')
end)()
end
game:BindToClose(function()
for i,v in pairs(game.Players:GetPlayers()) do
save(v)
end
end)
Everything seems pretty good, although you need to implement the use of pcalls in your script. To handle errors properly, and you can do like a repeat loop till data is saved successfully too.
Really simple Example, to get an idea:
local success, response
local tries = 0
local function saveData()
local saveData = {v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value}
success, response = pcall(moneystore.SetAsync, moneystore, v.UserId, saveData)
tries += 1
end
repeat
wait(7) --So that you don't hit limit of 6 second gap.
saveData()
until success == true or tries >= 3 --Will try 3 tries to save on max, or till you are not successful saving data.
local function save(v)
local a = coroutine.wrap(function()
moneystore:SetAsync(v.UserId,{v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value})
print(‘jiesh’)
end)
coroutine.resume(a)
end
It was to be taken as an example and get an idea, not copy paste that code (If you did, not sure), I really recommend you getting more understanding of what is causing the problem. The coroutine isn’t what is really causing the problem. Make sure you aren’t getting any error in console, if you’re post them here so we can see the error.
@VeinTweek coroutine.wrap doesn’t return the newly created thread, it just returns the function so that will result in an error.
Your method does not seem to work, and freezes studio.
local datastore = game:GetService("DataStoreService")
local moneystore = datastore:GetDataStore("Stats")
game.Players.PlayerAdded:Connect(function(p)
local leader = Instance.new("IntValue",p)
leader.Name = "leaderstats"
local mon = Instance.new("NumberValue",leader)
mon.Name = "Money"
local so = Instance.new("StringValue",leader)
so.Name = "Job"
local ren = Instance.new("NumberValue",leader)
ren.Name = "Reputation"
local gor = moneystore:GetAsync(p.UserId)
if gor~=nil then
mon.Value = gor[1]
so.Value = gor[2]
ren.Value = gor[3]
else
gor = {mon.Value,so.Value,ren.Value}
end
for i,v in pairs(script.Notice:GetChildren()) do
local sog = v:Clone()
sog.Parent = p
end
end)
game.Players.PlayerRemoving:Connect(function(p)
moneystore:SetAsync(p.UserId,{p.leaderstats.Money.Value,p.leaderstats.Job.Value,p.leaderstats.Reputation.Value})
print('sag')
end)
local success, response
local tries = 0
local function save(v)
local a = coroutine.wrap(function()
pcall(moneystore.SetAsync, moneystore, v.UserId, {p.leaderstats.Money.Value,p.leaderstats.Job.Value,p.leaderstats.Reputation.Value})
print('jiesh')
end)
tries += 1
end
game:BindToClose(function()
repeat
wait(7)
for i,v in pairs(game.Players:GetPlayers()) do
save(v)
end
until success == true or tries >= 3
end)
As per your current script, doesn’t look like you’re even understanding the basics. I mean like you need to use some logic in this case.
Some mistakes I found out with a look:
You aren’t executing the coroutine again, even though I already showed how to.
I had shown you to retry the save function if failed, what you’re doing is just infinite loop it around all the players and running save function inside it, of course resulting in a crash.
You aren’t even setting the success and response variable to the pcall’s return value.
You’re trying to reference the variable p in the save function, which isn’t defined.
What you should be doing is something like this:
local datastore = game:GetService("DataStoreService")
local moneystore = datastore:GetDataStore("Stats")
game.Players.PlayerAdded:Connect(function(p)
local leader = Instance.new("IntValue",p)
leader.Name = "leaderstats"
local mon = Instance.new("NumberValue",leader)
mon.Name = "Money"
local so = Instance.new("StringValue",leader)
so.Name = "Job"
local ren = Instance.new("NumberValue",leader)
ren.Name = "Reputation"
local gor = moneystore:GetAsync(p.UserId)
if gor~=nil then
mon.Value = gor[1]
so.Value = gor[2]
ren.Value = gor[3]
else
gor = {mon.Value,so.Value,ren.Value}
end
for i,v in pairs(script.Notice:GetChildren()) do
local sog = v:Clone()
sog.Parent = p
end
end)
local function save(v)
coroutine.wrap(function()
local success, response
local tries = 0
local saveData = {v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value}
success, response = pcall(moneystore.SetAsync, moneystore, v.UserId, saveData)
repeat
wait(7)
success, response = pcall(moneystore.SetAsync, moneystore, v.UserId, saveData)
tries += 1
until not success or tries < 3
end)()
end
game.Players.PlayerRemoving:Connect(function(p)
save(p)
end)
game:BindToClose(function()
for i,v in pairs(game.Players:GetPlayers()) do
save(v)
end
end)
Hello,
The solution you gave is still not working.
local datastore = game:GetService("DataStoreService")
local moneystore = datastore:GetDataStore("Stats")
game.Players.PlayerAdded:Connect(function(p)
local leader = Instance.new("IntValue",p)
leader.Name = "leaderstats"
local mon = Instance.new("NumberValue",leader)
mon.Name = "Money"
local so = Instance.new("StringValue",leader)
so.Name = "Job"
local ren = Instance.new("NumberValue",leader)
ren.Name = "Reputation"
local gor = moneystore:GetAsync(p.UserId)
if gor~=nil then
mon.Value = gor[1]
so.Value = gor[2]
ren.Value = gor[3]
else
gor = {mon.Value,so.Value,ren.Value}
end
for i,v in pairs(script.Notice:GetChildren()) do
local sog = v:Clone()
sog.Parent = p
end
end)
local function save(v)
coroutine.wrap(function()
local success, response
local tries = 0
local saveData = {v.leaderstats.Money.Value,v.leaderstats.Job.Value,v.leaderstats.Reputation.Value}
success, response = pcall(moneystore.SetAsync, moneystore, v.UserId, saveData)
repeat
wait(7)
success, response = pcall(moneystore.SetAsync, moneystore, v.UserId, saveData)
tries += 1
until not success or tries < 3
end)()
end
game.Players.PlayerRemoving:Connect(function(p)
save(p)
end)
game:BindToClose(function()
for i,v in pairs(game.Players:GetPlayers()) do
save(v)
end
end)
Are you sure the script is saved and then the game is run? Are you sure the API Services are turned on in studio? Use the pcalls while loading data too, to ensure its loading the data without any errors. Try and see if it works in Roblox player but not studio.
Also wanted to ensure that you’re updating your data from the server side.
I also don’t recommend you to copy paste, first you need to have an understanding of what the code does.