I have this script to save the players walk speed and jump height but everytime I join the game it sets them to zero and does not save them. Here’s the code:
local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")
game.Players.PlayerAdded:Connect(function(player)
local Character = workspace:WaitForChild(player.Name)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local PetsFolder = Instance.new("Folder")
PetsFolder.Name = "Pets"
PetsFolder.Parent = player
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
local jumps = Instance.new("IntValue")
jumps.Name = "Jumps"
jumps.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Parent = leaderstats
local data
local data1
local data2
local data3
local data4
local success, errormessage = pcall(function()
data = myDataStore:GetAsync(player.UserId.."-coins")
data1 = myDataStore:GetAsync(player.UserId.."-rebirths")
data2 = myDataStore:GetAsync(player.UserId.."-jumps")
data3 = myDataStore:GetAsync(player.UserId.."-jumpHeight")
data4 = myDataStore:GetAsync(player.UserId.."-walkSpeed")
end)
if success then
coins.Value = data
rebirths.Value = data1
jumps.Value = data2
Character.Humanoid.JumpHeight = data3
Character.Humanoid.WalkSpeed = data4
else
print("There was an error getting your data")
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
myDataStore:SetAsync(player.UserId.."-coins",player.leaderstats.Coins.Value)
myDataStore:SetAsync(player.UserId.."-rebirths",player.leaderstats.Rebirths.Value)
myDataStore:SetAsync(player.UserId.."-jumps",player.leaderstats.Jumps.Value)
myDataStore:SetAsync(player.UserId.."-jumpHeight",workspace[player.Name].Humanoid.JumpHeight)
myDataStore:SetAsync(player.UserId.."-walkSpeed",workspace[player.Name].Humanoid.WalkSpeed)
end)
if success then
print("Player data was successfully saved!")
else
print("There was an error while saving data")
warn(errormessage)
end
end)
It also gets this error that I don’t know how to fix
06:28:00.704 There was an error while saving data - Server
06:28:00.705 SuperEmeraldMaster1 is not a valid member of Workspace "Workspace" - Server
Here’s an example of me saving two values in a table into one datastore
game.Players.PlayerRemoving:Connect(function(player)
local UserId = "Player_"..player.UserId --Player's UserId
local pointsdata = {
WR = player.leaderstats.WR.Value,
Coins = player.leaderstats.Coins.Value
}
local success, errormessage = pcall(function() --Saving Data
PointsDataStore:SetAsync(UserId, pointsdata)
end)
if success then
print("Data Successfully Saved")
else
print("Error with Data Saving")
warn(errormessage)
end
end)
local UserId = "Player_"..player.UserId --Player's UserId
local pointsdata
local success, errormessage = pcall(function() --Loading Data
pointsdata = PointsDataStore:GetAsync(UserId)
end)
if success then --Transferring data to game
if pointsdata then
WR.Value = pointsdata.WR
Coins.Value = pointsdata.Coins
end
end
local pointsdata
local success, errormessage = pcall(function()
pointsdata = myDataStore:GetAsync(UserId)
end)
if success then
coins.Value = pointsdata[1]
rebirths.Value = pointsdata[2]
jumps.Value = pointsdata[3]
Character.Humanoid.JumpHeight = pointsdata[4]
Character.Humanoid.WalkSpeed = pointsdata[5]
print(data)
else
print("There was an error getting your data")
warn(errormessage)
end
Also, instead of local Character = workspace:WaitForChild(player.Name) why don’t you just do local Character = player.Character
As you said SuperGuy is not a valid member of workspace, here when the player leaves, the character gets deleted immediately
You should probably go with CharacterRemoving function, and when the function fires, make a dictionary of the values your saving when the player leaves
Hope you know how to do it as you know how to make a saving system, so when the player leaves get the info from the table and than remove the table after done
The thing is, the character gets deleted, so its not a valid member, you should go for CharacterRemoving than PlayerRemoving
When a player leaves, the character gets deleted first, then the player instance, so when you fire this when the player removing event is fired, the character does not exist as it gets removed earlier, so you shouldn’t do this if your saving a character value
local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")
game.Players.PlayerAdded:Connect(function(player)
local Character = player.Character or player.CharacterAdded:Wait()
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local PetsFolder = Instance.new("Folder")
PetsFolder.Name = "Pets"
PetsFolder.Parent = player
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
local jumps = Instance.new("IntValue")
jumps.Name = "Jumps"
jumps.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Parent = leaderstats
local data
local data1
local data2
local data3
local data4
local success, errormessage = pcall(function()
data = myDataStore:GetAsync(player.UserId.."-coins")
data1 = myDataStore:GetAsync(player.UserId.."-rebirths")
data2 = myDataStore:GetAsync(player.UserId.."-jumps")
data3 = myDataStore:GetAsync(player.UserId.."-jumpHeight")
data4 = myDataStore:GetAsync(player.UserId.."-walkSpeed")
end)
if success then
coins.Value = data
rebirths.Value = data1
jumps.Value = data2
Character.Humanoid.JumpHeight = data3
Character.Humanoid.WalkSpeed = data4
else
print("There was an error getting your data")
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
myDataStore:SetAsync(player.UserId.."-coins",player.leaderstats.Coins.Value)
myDataStore:SetAsync(player.UserId.."-rebirths",player.leaderstats.Rebirths.Value)
myDataStore:SetAsync(player.UserId.."-jumps",player.leaderstats.Jumps.Value)
myDataStore:SetAsync(player.UserId.."-jumpHeight",workspace[player.Name].Humanoid.JumpHeight)
myDataStore:SetAsync(player.UserId.."-walkSpeed",workspace[player.Name].Humanoid.WalkSpeed)
end)
if success then
print("Player data was successfully saved!")
else
print("There was an error while saving data")
warn(errormessage)
end
end)
If the player dies the walk speed/jump power would be reset if you take this approach. If I were you I would use character added function so if the player dies the jump power and the speed will not reset. The problem with this if you are constantly changing the player’s speed/jump power, what the data was then that would be it’s speed/jump power.
And if you’r saving multiple data then using a dictionary is a must since there are server limits.
your trying the get the players character in the PlayerRemoving event and the character has already been destroyed
you calling SetAsync a lot of time while you have not hit the limit it better to call SetAsync once and save all the players data in a table (see the limits here Data Stores)
when the last player leaves the game the server is shutting down and might not save the last players data you need to use bindtoclose to keep the server running while you save the last players data
here is some demo code on how to save all the data in a single table and also how to use bindtoclose
local playerLoaded = {}
game.Players.PlayerAdded:Connect(function(player)
-- when the player enters the game try to load there data
local success, value = pcall(dataStore.GetAsync, dataStore, player.UserId)
if success == false then return end
-- if the value = nil then set value to a empty table
value = value or {}
-- clone the data folder inside this script with all its values
local folder = script.Data:Clone()
-- loop all values and set them to match what was last saved in the datastore
for i, child in ipairs(folder) do child.Value = value[child.Name] or child.Value end
-- place the folder into the player
folder.Parent = player
-- set the playerloaded to true so we can keep track if there are players loaded so that bind to close can wait
playerLoaded[player] = true
end)
game.Players.PlayerRemoving:Connect(function(player)
-- if player loaded == nil meaning the player failed to load when they entered we simple exit because we dont want to overwrite the old data
if playerLoaded[player] == nil then return end
-- create a table and set the the values from there data folder
local playerData = {}
for i, child in ipairs(player.Data:GetChildren()) do
playerData[child.Name] = child.Value
end
-- now save this table to the datastore
local success, value = pcall(dataStore.SetAsync, dataStore, player.UserId, playerData)
-- now set playerLoaded to nil so that bindtoclose can stop looping and allow the server to close
playerLoaded[player] = nil
end)
-- while players are loaded dont close the server (only works upto 30 seconds)
game:BindToClose(function()
while next(playerLoaded) ~= nil do
task.wait()
end
end)