Datastore not working

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
3 Likes

Why are you trying to load all the data through one pcall?

I don’t think it’s possible to save all that data through one pcall

1 Like

I’m not good with data stores and that’s just the way I learned it. Is it bad?

How would you do it? Because I have no idea

You can save everything to one datastore using a table

1 Like

Could you give me an example? I don’t know how to do that

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)
3 Likes

How would you then load that data when they join?

Make a saving table like this:

local savingTable = {player.PetsFolder.Value;
    player.leaderstats.Coins.Value;
    player.leaderstats.Jumps.Value;
    player.leaderstats.Rebirths.Value
}

So your myDataStore:SetAsync can be written like this: myDataStore:SetAsync(player.UserId, savingTable).

You can load the data like this

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

Well, it’s pretty straight forward and organized.

I just followed your example and I got some errors

Code:

 local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")


game.Players.PlayerAdded:Connect(function(player)
	local Character = workspace:WaitForChild(player.Name)
	local UserId = "Player_"..player.UserId
	
	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 pointsdata
	local success, errormessage = pcall(function()
		pointsdata = myDataStore:GetAsync(UserId)
	end)
	
	if success then
		coins.Value = pointsdata.Coins
		rebirths.Value = pointsdata.Rebirths
		jumps.Value = pointsdata.Jumps
		Character.Humanoid.JumpHeight = pointsdata.JumpHeight
		Character.Humanoid.WalkSpeed = pointsdata.WalkSpeed
	else
		print("There was an error getting your data")
		warn(errormessage)
	end	
end)

game.Players.PlayerRemoving:Connect(function(player)
	local UserId = "Player_"..player.UserId
	
	local pointsdata = {
		Rebirths = player.leaderstats.Rebirths.Value,
		Coins = player.leaderstats.Coins.Value,
		Jumps = player.leaderstats.Jumps.Value,
		WalkSpeed = game.Workspace[player.Name]:FindFirstChild("Humanoid").WalkSpeed,
		JumpHeight = game.Workspace[player.Name]:FindFirstChild("Humanoid").JumpHeight
		
	}
	
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(UserId, pointsdata)
	end)
	
	if success then
		print("Player data was successfully saved!")
	else
		print("There was an error while saving data")
		warn(errormessage)
	end
end)

Error:

ServerScriptService.leaderstats:35: attempt to index nil with 'Coins'
SuperEmeraldMaster1 is not a valid member of Workspace "Workspace"

This also does not help with my original problem which is that the walk speed and jump height are not getting saved

Try this:

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

If data is nil, there is no data saved.

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)

Are API requests, switched on?

I thought data stores need API atudio access, not HTTP.

Yeah, I’m pretty sure they don’t need HTTP requests switched on. I have it working perfectly and I never use that.

1 Like

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.

so i can see a few problems

  1. your trying the get the players character in the PlayerRemoving event and the character has already been destroyed

  2. 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)

  3. 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)
1 Like