I have made this data saving script with tutorials on Youtube (I understand the code and I didnt just copy paste it). When I left the game on studio, it doesnt “Print” anything when the player left. Making the data of the user not getting saved. I have tried playing the game itself outside the studio but still it doesnt work. I have turned on API service on roblox studio and there is no error printing. What could be the issue?
v Whole Script v
local Players = game:GetService("Players")
local SS = game:GetService("ServerStorage")
local DS = game:GetService("DataStoreService")
local playerDataStore = DS:GetDataStore("MainData")
local playerTable = {}
--[Functions]--
-->Add Speed
function addSpeed()
while wait(1) do
for i, plr in pairs(playerTable) do
local chr = plr.Character or plr.CharacterAdded:Wait()
local speed = plr.leaderstats.Speed
local Humanoid = chr:WaitForChild("Humanoid")
speed.Value += 1
Humanoid.WalkSpeed = speed.Value * 0.05
end
end
end
function saveData(plr)
print("Saving")
local leaderstats = plr.leaderstats
local playerData = {leaderstats.Speed.Value, leaderstats.Wins.Value}
local succ, err = pcall(function()
playerDataStore:SetAsync(plr.UserId, playerData)
end)
if not succ then warn(err) end
end
--[Main]--
--> Player Joining
Players.PlayerAdded:Connect(function(plr)
--Add speed and leaderboard
local leaderboard = Instance.new("Folder")
leaderboard.Parent = plr
leaderboard.Name = "leaderstats"
local Speed = Instance.new("NumberValue")
Speed.Name = "Speed"
Speed.Parent = leaderboard
Speed.Value = 1
local Wins = Instance.new("NumberValue")
Wins.Name = "Wins"
Wins.Parent = leaderboard
Wins.Value = 0
local Zone = Instance.new("StringValue")
Zone.Name = "Zone"
Zone.Parent = plr
Zone.Value = "Zone 1"
local trailFolder = Instance.new("Folder")
trailFolder.Parent = plr
trailFolder.Name = "Trail"
local playerData
local succ, err = pcall(function()
local playerID = plr.UserId
playerData = playerDataStore:GetAsync(playerID)
end)
print(playerData ,succ, err)
if succ then
if playerData then
Speed.Value = playerData.Speed
Wins.Value = playerData.Wins
print("Has")
else
print("Has not")
Speed.Value = 1
Wins.Value = 0
end
else
warn(err)
Speed.Value = 1
Wins.Value = 0
end
plr.CharacterAdded:Connect(function(chr)
local BBGui = SS.Misc.playerBillboard:Clone()
BBGui.Parent = chr.Head
BBGui.Main.userName.Text = plr.Name
BBGui.Main.userSpeed.Text = "👟: "..Speed.Value
BBGui.Main.userWins.Text = "🏆:"..Wins.Value
local trailAttachment = SS.Misc.TrailAttachment:Clone()
trailAttachment.Parent = chr
trailAttachment.Weld.Part1 = chr.HumanoidRootPart
for _, trail in pairs(plr.Trail:GetChildren()) do
if trail:GetAttribute("Equip") == true then
local trail = trail:Clone()
trail.Parent = trailAttachment
trail.Attachment0 = trailAttachment.Attachment1
trail.Attachment1 = trailAttachment.Attachment2
break
end
end
chr.Humanoid.WalkSpeed = Speed.Value * 0.05
end)
table.insert(playerTable, plr)
end)
addSpeed()
Players.PlayerRemoving:Connect(function(plr)
print("Leaving")
saveData(plr)
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
saveData(plr)
end
end)
Ok I see the problem.
This is how you load the values:
Speed.Value = playerData.Speed
Wins.Value = playerData.Wins
Which in theory it would work, the problem is that PlayerData doesnt have a Speed Value.
How to fix this?
In your save function do this instead:
-- Currrent
local playerData = {leaderstats.Speed.Value, leaderstats.Wins.Value}
-- What should work
local playerData = {
Speed = leaderstats.Speed.Value,
Wins = leaderstats.Wins.Value
}
See by just putting the values into a table it sets the key for the item stored as a number, with this we can set it to what we want!
Hope this works!
1 Like
You cannot save arrays in a datastore, instead, you’ll have to encode them using JSON, and decode them after. You can achieve this by using HttpService
. Also, you saved it as an array, but tried to load it as a dictionary. The code below should work:
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local SS = game:GetService("ServerStorage")
local DS = game:GetService("DataStoreService")
local playerDataStore = DS:GetDataStore("MainData")
local playerTable = {}
--[Functions]--
-->Add Speed
function addSpeed()
while wait(1) do
for i, plr in pairs(playerTable) do
local chr = plr.Character or plr.CharacterAdded:Wait()
local speed = plr.leaderstats.Speed
local Humanoid = chr:WaitForChild("Humanoid")
speed.Value += 1
Humanoid.WalkSpeed = speed.Value * 0.05
end
end
end
function saveData(plr)
print("Saving")
local leaderstats = plr.leaderstats
local playerData = {["Speed"] = leaderstats.Speed.Value; ["Wins"] = leaderstats.Wins.Value;}
local succ, err = pcall(function()
playerDataStore:SetAsync(plr.UserId, HttpService:JSONEncode(playerData))
end)
if not succ then warn(err) end
end
--[Main]--
--> Player Joining
Players.PlayerAdded:Connect(function(plr)
--Add speed and leaderboard
local leaderboard = Instance.new("Folder")
leaderboard.Parent = plr
leaderboard.Name = "leaderstats"
local Speed = Instance.new("NumberValue")
Speed.Name = "Speed"
Speed.Parent = leaderboard
Speed.Value = 1
local Wins = Instance.new("NumberValue")
Wins.Name = "Wins"
Wins.Parent = leaderboard
Wins.Value = 0
local Zone = Instance.new("StringValue")
Zone.Name = "Zone"
Zone.Parent = plr
Zone.Value = "Zone 1"
local trailFolder = Instance.new("Folder")
trailFolder.Parent = plr
trailFolder.Name = "Trail"
local playerData
local succ, err = pcall(function()
local playerID = plr.UserId
playerData = HttpService:JSONDecode(playerDataStore:GetAsync(playerID))
end)
print(playerData ,succ, err)
if succ then
if playerData then
Speed.Value = playerData["Speed"]
Wins.Value = playerData["Wins"}
print("Has")
else
print("Has not")
Speed.Value = 1
Wins.Value = 0
end
else
warn(err)
Speed.Value = 1
Wins.Value = 0
end
plr.CharacterAdded:Connect(function(chr)
local BBGui = SS.Misc.playerBillboard:Clone()
BBGui.Parent = chr.Head
BBGui.Main.userName.Text = plr.Name
BBGui.Main.userSpeed.Text = "👟: "..Speed.Value
BBGui.Main.userWins.Text = "🏆:"..Wins.Value
local trailAttachment = SS.Misc.TrailAttachment:Clone()
trailAttachment.Parent = chr
trailAttachment.Weld.Part1 = chr.HumanoidRootPart
for _, trail in pairs(plr.Trail:GetChildren()) do
if trail:GetAttribute("Equip") == true then
local trail = trail:Clone()
trail.Parent = trailAttachment
trail.Attachment0 = trailAttachment.Attachment1
trail.Attachment1 = trailAttachment.Attachment2
break
end
end
chr.Humanoid.WalkSpeed = Speed.Value * 0.05
end)
table.insert(playerTable, plr)
end)
addSpeed()
Players.PlayerRemoving:Connect(function(plr)
print("Leaving")
saveData(plr)
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
saveData(plr)
end
end)
1 Like
Datastore service automatically uses JSONEncode and JSONDecode by default so there isnt a reason to do this.
That and again they reference something that doesnt exist like I said in my reply :]
I tried your code and it prints the “err”. It says “Argument missing 1 or nil”. What should I do?
I tried this but still, no luck and it doesnt work… thank you though
1 Like
When the player leaves, it doesnt print anything or like the function when the player leaves doesnt run. Is there a way to fix this?
Can I see your code with my changes? There could be another problem, but the thing I mentioned is still a part of the problem, at least from the look of it
I only changed the line that you mentioned
local Players = game:GetService("Players")
local SS = game:GetService("ServerStorage")
local DS = game:GetService("DataStoreService")
local playerDataStore = DS:GetDataStore("MainData")
local playerTable = {}
--[Functions]--
-->Add Speed
function addSpeed()
while wait(1) do
for i, plr in pairs(playerTable) do
local chr = plr.Character or plr.CharacterAdded:Wait()
local speed = plr.leaderstats.Speed
local Humanoid = chr:WaitForChild("Humanoid")
speed.Value += 1
Humanoid.WalkSpeed = speed.Value * 0.05
end
end
end
--> Save player data
function saveData(plr)
print("Saving")
local leaderstats = plr.leaderstats
local playerData = {
Speed = leaderstats.Speed.Value,
Wins = leaderstats.Wins.Value}
local succ, err = pcall(function()
playerDataStore:SetAsync(plr.UserId, playerData)
end)
if not succ then warn(err) end
end
--[Main]--
--> Player Joining
Players.PlayerAdded:Connect(function(plr)
--Add speed and leaderboard
local leaderboard = Instance.new("Folder")
leaderboard.Parent = plr
leaderboard.Name = "leaderstats"
local Speed = Instance.new("NumberValue")
Speed.Name = "Speed"
Speed.Parent = leaderboard
Speed.Value = 1
local Wins = Instance.new("NumberValue")
Wins.Name = "Wins"
Wins.Parent = leaderboard
Wins.Value = 0
local Zone = Instance.new("StringValue")
Zone.Name = "Zone"
Zone.Parent = plr
Zone.Value = "Zone 1"
local trailFolder = Instance.new("Folder")
trailFolder.Parent = plr
trailFolder.Name = "Trail"
local playerData
local succ, err = pcall(function()
local playerID = plr.UserId
playerData = playerDataStore:GetAsync(playerID)
end)
print(playerData ,succ, err)
if succ then
if playerData then
Speed.Value = playerData.Speed
Wins.Value = playerData.Wins
print("Has")
else
print("Has not")
Speed.Value = 1
Wins.Value = 0
end
else
warn(err)
Speed.Value = 1
Wins.Value = 0
end
plr.CharacterAdded:Connect(function(chr)
local BBGui = SS.Misc.playerBillboard:Clone()
BBGui.Parent = chr.Head
BBGui.Main.userName.Text = plr.Name
BBGui.Main.userSpeed.Text = "👟: "..Speed.Value
BBGui.Main.userWins.Text = "🏆:"..Wins.Value
local trailAttachment = SS.Misc.TrailAttachment:Clone()
trailAttachment.Parent = chr
trailAttachment.Weld.Part1 = chr.HumanoidRootPart
for _, trail in pairs(plr.Trail:GetChildren()) do
if trail:GetAttribute("Equip") == true then
local trail = trail:Clone()
trail.Parent = trailAttachment
trail.Attachment0 = trailAttachment.Attachment1
trail.Attachment1 = trailAttachment.Attachment2
break
end
end
chr.Humanoid.WalkSpeed = Speed.Value * 0.05
end)
table.insert(playerTable, plr)
end)
addSpeed()
game.Players.PlayerRemoving:Connect(function(plr)
print("Leaving")
table.remove(playerTable, table.find(playerTable, plr))
saveData(plr)
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
saveData(plr)
end
end)
Ohh wait I see now.
So you call the addSpeed function, of which never stops running, thus the game never connects the RbxEvent .PlayerRemoving!
Simple fix!
task.spawn!
Just replace your code:
local Players = game:GetService("Players")
local SS = game:GetService("ServerStorage")
local DS = game:GetService("DataStoreService")
local playerDataStore = DS:GetDataStore("MainData")
local playerTable = {}
--[Functions]--
-->Add Speed
function addSpeed()
while wait(1) do
for i, plr in pairs(playerTable) do
local chr = plr.Character or plr.CharacterAdded:Wait()
local speed = plr.leaderstats.Speed
local Humanoid = chr:WaitForChild("Humanoid")
speed.Value += 1
Humanoid.WalkSpeed = speed.Value * 0.05
end
end
end
--> Save player data
function saveData(plr)
print("Saving")
local leaderstats = plr.leaderstats
local playerData = {
Speed = leaderstats.Speed.Value,
Wins = leaderstats.Wins.Value}
local succ, err = pcall(function()
playerDataStore:SetAsync(plr.UserId, playerData)
end)
if not succ then warn(err) end
end
--[Main]--
--> Player Joining
Players.PlayerAdded:Connect(function(plr)
--Add speed and leaderboard
local leaderboard = Instance.new("Folder")
leaderboard.Parent = plr
leaderboard.Name = "leaderstats"
local Speed = Instance.new("NumberValue")
Speed.Name = "Speed"
Speed.Parent = leaderboard
Speed.Value = 1
local Wins = Instance.new("NumberValue")
Wins.Name = "Wins"
Wins.Parent = leaderboard
Wins.Value = 0
local Zone = Instance.new("StringValue")
Zone.Name = "Zone"
Zone.Parent = plr
Zone.Value = "Zone 1"
local trailFolder = Instance.new("Folder")
trailFolder.Parent = plr
trailFolder.Name = "Trail"
local playerData
local succ, err = pcall(function()
local playerID = plr.UserId
playerData = playerDataStore:GetAsync(playerID)
end)
print(playerData ,succ, err)
if succ then
if playerData then
Speed.Value = playerData.Speed
Wins.Value = playerData.Wins
print("Has")
else
print("Has not")
Speed.Value = 1
Wins.Value = 0
end
else
warn(err)
Speed.Value = 1
Wins.Value = 0
end
plr.CharacterAdded:Connect(function(chr)
local BBGui = SS.Misc.playerBillboard:Clone()
BBGui.Parent = chr.Head
BBGui.Main.userName.Text = plr.Name
BBGui.Main.userSpeed.Text = "👟: "..Speed.Value
BBGui.Main.userWins.Text = "🏆:"..Wins.Value
local trailAttachment = SS.Misc.TrailAttachment:Clone()
trailAttachment.Parent = chr
trailAttachment.Weld.Part1 = chr.HumanoidRootPart
for _, trail in pairs(plr.Trail:GetChildren()) do
if trail:GetAttribute("Equip") == true then
local trail = trail:Clone()
trail.Parent = trailAttachment
trail.Attachment0 = trailAttachment.Attachment1
trail.Attachment1 = trailAttachment.Attachment2
break
end
end
chr.Humanoid.WalkSpeed = Speed.Value * 0.05
end)
table.insert(playerTable, plr)
end)
task.spawn(addSpeed) -- This is a fix hopefully
game.Players.PlayerRemoving:Connect(function(plr)
print("Leaving")
table.remove(playerTable, table.find(playerTable, plr))
saveData(plr)
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
saveData(plr)
end
end)
(If you want to see what changed, just look for where you call the addSpeed function).
So the problem is that the addSpeed function is a while loop that will run forever, hence stopping any code after the point you triggered the function, but using task.spawn it ignores the yield of the function, hence allowing all of the other code to run!
1 Like
Thank you so much for the help and also @PagomenosOruxeiosss, thank you.
It is fixed now. The “task.spawn” fixed the problem. I didnt notice that the while loop is causing the problem
2 Likes