Saving player walk speed and jump power stats with datastore

I’m trying to make it so the game saves the player’s walkspeed and jumppower after they leave the game or die with a datastore.

I think the datastore is being set up fine but it won’t update/save the player’s stats when they die or leave.

I have two scripts, both in the server script service. The first one sets up the datastore and the second one sets updates the player’s stats to the ones saved in the datastore

First script:

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("ExtraData")

local function onPlayerJoin(player)  -- Runs when players join
	local leaderstats = Instance.new("Folder")  --Sets up leaderstats folder
	leaderstats.Name = "extrastats"
	leaderstats.Parent = player

	local speed = Instance.new("IntValue") --Sets up value for leaderstats
	speed.Name = "Speed"
	speed.Parent = leaderstats

	local jump = Instance.new("IntValue") --Sets up value for leaderstats
	jump.Name = "Jump"
	jump.Parent = leaderstats
	
	local level = Instance.new("IntValue") --Sets up value for leaderstats
	level.Name = "idk"
	level.Parent = leaderstats

	local playerUserId = "Player_" .. player.UserId  --Gets player ID
	local edata = playerData:GetAsync(playerUserId)  --Checks if player has stored data
	if edata then
		speed.Value = edata['Speed']
		jump.Value = edata['Jump']
		level.Value = edata['idk']
	else
		-- Data store is working, but no current data for this player, (starting value)
		speed.Value = 20
		jump.Value = 30
		level.Value = 0
	end
end

local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function onPlayerExit(player)  --Runs when players exit
	local player_stats = create_table(player)
	local success, err = pcall(function()
		local playerUserId = "Player_" .. player.UserId
		playerData:SetAsync(playerUserId, player_stats) --Saves player data
	end)

	if not success then
		warn('Could not save data!')
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)

Second script:

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(Player)
	local jump = Player:WaitForChild("extrastats").Jump
	local speed = Player:WaitForChild("extrastats").Speed

	Player.CharacterAdded:Connect(function(Character)

		local Humanoid = Character:FindFirstChild("Humanoid")
		speed.Value = Humanoid.WalkSpeed
		jump.Value = Humanoid.JumpPower

	end)
end)

I have tried looking for answers on google and here but I’ve just gotten a bit stuck and would appreciate any help, thanks!

.

3 Likes

This code looks like it’s built from different sources by copy-pasting.
You’re having a race-condition issue, PlayerAdded event is called and both consumers are invoked at the same time. This means that your consumer in second script doesn’t have data of extrastats, before first consumer hasn’t finished yet, loading data from datastore takes significant time from the view of second consumer.
Wise would be merging both consumers into one, so your script can properly load data from datastore and then use these extrastats.

5 Likes

does this part actually run the warning part

1 Like

No, I don’t think any of the print functions work.

1 Like

I tried doing that but it’s still not working:

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("ExtraData")

local function onPlayerJoin(player)  -- Runs when players join
	local leaderstats = Instance.new("Folder")  --Sets up leaderstats folder
	leaderstats.Name = "extrastats"
	leaderstats.Parent = player

	local speed = Instance.new("IntValue") --Sets up value for leaderstats
	speed.Name = "Speed"
	speed.Parent = leaderstats

	local jump = Instance.new("IntValue") --Sets up value for leaderstats
	jump.Name = "Jump"
	jump.Parent = leaderstats
	
	local level = Instance.new("IntValue") --Sets up value for leaderstats
	level.Name = "idk"
	level.Parent = leaderstats

	local playerUserId = "Player_" .. player.UserId  --Gets player ID
	local edata = playerData:GetAsync(playerUserId)  --Checks if player has stored data
	if edata then
		speed.Value = edata['Speed']
		jump.Value = edata['Jump']
		level.Value = edata['idk']

	else
		-- Data store is working, but no current data for this player, (starting value)
		speed.Value = 20
		jump.Value = 30
		level.Value = 0

	end
	player.CharacterAdded:Connect(function(Character)

		local Humanoid = Character:FindFirstChild("Humanoid")
		speed.Value = Humanoid.WalkSpeed
		jump.Value = Humanoid.JumpPower

	end)
end

local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function onPlayerExit(player)  --Runs when players exit
	local player_stats = create_table(player)
	local success, err = pcall(function()
		local playerUserId = "Player_" .. player.UserId
		playerData:SetAsync(playerUserId, player_stats) --Saves player data
	end)

	if not success then
		warn('Could not save data!')
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
1 Like

Because your code is wrong. You want to load speed and jump power into the humanoid…

    player.CharacterAdded:Connect(function(Character)
		local Humanoid = Character:FindFirstChild("Humanoid")
		Humanoid.WalkSpeed = speed.Value
		Humanoid.JumpPower = jump.Value
		print("Character loaded")
	end)

Check in your console if Character loaded has appeared, if not, your character has been loaded in mean-time. Better solution to this would probably be

local characterAdjust = function(Character)
    local Humanoid = Character:FindFirstChild("Humanoid")
    Humanoid.WalkSpeed = speed.Value
    Humanoid.JumpPower = jump.Value
    print("Character loaded")
end
if (player.Character) then characterAdjust(player.Character)
else player.CharacterAdded:Connect(characterAdjust) end
1 Like

It prints Character added but when the game loads, I can’t move my character at all presumably because the speed/jump stats are set to 0?

1 Like

There’s no data in the datastore, then you must make a fallback if there are no data. For example check for nil or zeroes.

1 Like

– Variables

local DSS = game:GetService(“DataStoreService”):GetDataStore(“DSS”)

– Code

game.Players.PlayerAdded:Connect(function(plr)

local leaderstats = Instance.new(“Folder”, plr)
leaderstats.Name = “” --[[ Change this to the name of your leaderboard name it leaderboard if you want to see the leaderboard, if not set it to a random name, that’s you can remember --]]

local speed = Instance.new(“IntValue”, plr)
speed.Name = “speed”

local jump = Instance.new(“IntValue”, leaderstats)
jump.Name = “jump”

local level = Instance.new(“IntValue”, leaderstats)
level.Name = “level”

local data = DataStoreService:GetAsync(plr.UserId)

if data then
– We know the player has data

speed.Value = data.speed

Jump.Value = data.jump

level.Value = data.level

else

print(“First time playing”)

– Set to default values
speed.Value = 0
jump.Value = 0
level.Value = 0

end

player.CharacterAdded:Connect(function(char)

– Setting walkspeed and jumpower

speed.Value = char:WaitForChild(“Humanoid”).WalkSpeed
jump.Value = Humanoid.JumpPower

end)

end)

game.Players.PlayerRemoving:Connect(function(plr)

local TableGettingSaved = {}

for i, v in pairs(plr:WaitForChild(“leaderstats”):GetChildren()) do

table.insert(TableGettingSaved, {Name = v.Name, Value = v.Value})

end

DSS:SetAsync(plr.UserId, TableGettingSaved)

end)

– If you have any errors with this code please reply back and tell me the error message and i can give you the updated version of the code!

2 Likes

It already has that, here is an excerpt from my script

	if edata then
		speed.Value = edata['Speed']
		jump.Value = edata['Jump']
		level.Value = edata['idk']

	else
		-- Data store is working, but no current data for this player, (starting value)
		speed.Value = 20
		jump.Value = 30
		level.Value = 0

	end
	local characterAdjust = function(Character)
		local Humanoid = Character:FindFirstChild("Humanoid")
		Humanoid.WalkSpeed = speed.Value
		Humanoid.JumpPower = jump.Value
		print("Character loaded")
	end
1 Like

If your walkspeed is set to 0, that may the issue, if the walkspeed is set to zero, the player will not be able to walk, so maybe if you set speed to 2 - 3 that will make the player walk

1 Like

You are also using a characteradded which means anything that changes after the players character has loaded wont be applied to the player, so if the speed has been changed it wont be applied to the player, So try using while loop with a task.spawn, here’s the updated code: – Variables

local DSS = game:GetService(“DataStoreService”):GetDataStore(“DSS”)

– Code

game.Players.PlayerAdded:Connect(function(plr)

local leaderstats = Instance.new(“Folder”, plr)
leaderstats.Name = “” --[[ Change this to the name of your leaderboard name it leaderboard if you want to see the leaderboard, if not set it to a random name, that’s you can remember --]]

local speed = Instance.new(“IntValue”, plr)
speed.Name = “speed”

local jump = Instance.new(“IntValue”, leaderstats)
jump.Name = “jump”

local level = Instance.new(“IntValue”, leaderstats)
level.Name = “level”

local data = DataStoreService:GetAsync(plr.UserId)

if data then
– We know the player has data

speed.Value = data.speed

Jump.Value = data.jump

level.Value = data.level

else

print(“First time playing”)

– Set to default values
speed.Value = 0
jump.Value = 0
level.Value = 0

end

player.CharacterAdded:Connect(function(char)

task.spawn(function()

while wait() do

– Setting walkspeed and jumpower

speed.Value = char:WaitForChild(“Humanoid”).WalkSpeed
jump.Value = Humanoid.JumpPower

end

end)

end)

end)

game.Players.PlayerRemoving:Connect(function(plr)

local TableGettingSaved = {}

for i, v in pairs(plr:WaitForChild(“leaderstats”):GetChildren()) do

table.insert(TableGettingSaved, {Name = v.Name, Value = v.Value})

end

DSS:SetAsync(plr.UserId, TableGettingSaved)

end)

1 Like

Print values of Humanoid.WalkSpeed and JumpPower or check in Studio while playing if these values are properly set.

1 Like

Make sure that API Services is enabled in studio settings this may avoid errors occuring, but if API Services is enabled then there may be an issue with your saving code, you seem to be using a function to create a table, here’s a much understandable code that could potentially fix your error – do note this is for the saving of the datastore so replace game.Players.PlayerRemoving with this: game.Players.PlayerRemoving:Connect(function(plr)

local TableGettingSaved = {}

for i, v in pairs(plr:WaitForChild(“leaderstats”):GetChildren()) do

table.insert(TableGettingSaved, {Name = v.Name, Value = v.Value})

end

DSS:SetAsync(plr.UserId, TableGettingSaved)

end)

Ok, I printed them and they all printed 0.

Could you please tell me in detail what exactly prints zero, is it the jump and speed, if it is then its probably because you change your datastore name to a different name so that the values are resetted and then retest to see if that fixed the issues your currently experiencing!

API and HTTP is enabled already, I added that and nothing changed.

I apologise, if you where using my updated code, i forgot to set the core values properly: local DSS = game:GetService(“DataStoreService”):GetDataStore(“DSS”)

– Code

game.Players.PlayerAdded:Connect(function(plr)

local leaderstats = Instance.new(“Folder”, plr)
leaderstats.Name = “” --[[ Change this to the name of your leaderboard name it leaderboard if you want to see the leaderboard, if not set it to a random name, that’s you can remember --]]

local speed = Instance.new(“IntValue”, plr)
speed.Name = “speed”

local jump = Instance.new(“IntValue”, leaderstats)
jump.Name = “jump”

local level = Instance.new(“IntValue”, leaderstats)
level.Name = “level”

local data = DataStoreService:GetAsync(plr.UserId)

if data then
– We know the player has data

speed.Value = data.speed

Jump.Value = data.jump

level.Value = data.level

else

print(“First time playing”)

– Set to default values
speed.Value = 16
jump.Value = 30
level.Value = 0

end

player.CharacterAdded:Connect(function(char)

task.spawn(function()

while wait() do

– Setting walkspeed and jumpower

speed.Value = char:WaitForChild(“Humanoid”).WalkSpeed
jump.Value = Humanoid.JumpPower

end

end)

end)

end)

game.Players.PlayerRemoving:Connect(function(plr)

local TableGettingSaved = {}

for i, v in pairs(plr:WaitForChild(“leaderstats”):GetChildren()) do

table.insert(TableGettingSaved, {Name = v.Name, Value = v.Value})

end

DSS:SetAsync(plr.UserId, TableGettingSaved)

end) – This could potentially fix the issue your currently experiencing!

Here’s my updated script:

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

game.Players.PlayerAdded:Connect(function(plr)

	local leaderstats = Instance.new("Folder", plr)
	leaderstats.Name = "MoreData" --[[ Change this to the name of your leaderboard name it leaderboard if you want to see the leaderboard, if not set it to a random name, that’s you can remember --]]
	local speed = Instance.new("IntValue", plr)
	speed.Name = "speed"
	local jump = Instance.new("IntValue", leaderstats)
	jump.Name = "jump"
	local level = Instance.new("IntValue", leaderstats)
	level.Name = "level"

	local data = DSS:GetAsync(plr.UserId)

	if data then
		-- We know the player has data

		speed.Value = data.speed
		jump.Value = data.jump
		level.Value = data.level
		
		print("ExtraData script player data: "..speed.Value.." -Speed, "..jump.Value.." -Jump, "..level.Value.." -Level (not in use), ")
	else

		print("First Time playing")

		-- Set to default values
		speed.Value = 0
		jump.Value = 0
		level.Value = 0
	end

	plr.CharacterAdded:Connect(function(char)

		-- Setting walkspeed and jumpower

		speed.Value = char:WaitForChild("Humanoid").WalkSpeed
		jump.Value = char:WaitForChild("Humanoid").JumpPower

	end)
end)

game.Players.PlayerRemoving:Connect(function(plr)

	local TableGettingSaved = {}

	for i, v in pairs(plr:WaitForChild("MoreData"):GetChildren()) do

		table.insert(TableGettingSaved, {Name = v.Name, Value = v.Value})
	end
	
	DSS:SetAsync(plr.UserId, TableGettingSaved)
end)

Here’s my entire output log:

1 Like

Can you embed that please using the ```lua

1 Like