(STILL need help) Datastore not saving health

When someone is about to die without food (in game), they may leave. im trying to prevent that with a saving health script so they cant chicken out on their death and lose their money.

The problem is that the saved health isnt applying to the character or not saving.

I’ve tried looking through my code thoroughly.

theres nothing else to say. thanks for reading

local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("HealthSave")

game.Players.PlayerAdded:connect(function(player)
player.Character.Humanoid.Health = ds:GetAsync(player.UserId)
ds:SetAsync(player.UserId, player.Character.Humanoid.Health)
player.Character.Humanoid.Health.Changed:connect(function()
ds:SetAsync(player.UserId, player.Character.Humanoid.Health)
end)
end)

game.Players.PlayerRemoving:connect(function(player)
ds:SetAsync(player.UserId, player.Character.Humanoid.Health)
end)

1 Like

when the game.Players.PlayerRemoving event fires the character has already been destroyed so

player.Character will equal to nil

so to fix this problem you will have to use the CharacterAdded event and save a reference of the character into a table or something then when they leave use the reference in the table to get the health

local characters = {}

game.Players.PlayerAdded:connect(function(player)
	player.CharacterAdded:Connect(function(character)
		characters[player] = character -- save the new character into the characters table
	end)
end

game.Players.PlayerRemoving:connect(function(player)
	if characters[player] == nil then return end
	print(characters[player].Humanoid.Health)
	characters[player] = nil -- set to nil so we don't get a memory leak
end

I also wouldn’t recommend saving the players health every time it changes. Since you’re saving it when they leave, there’s no point saving in between. Otherwise you’re going to hit the setasync request limit very quickly which could also cause the datastore not to save

Like 5uphi said, I have my script in were saving it when they leave, it requests the character’s health (which is gone because they already left) so making it so when they leave may be a good idea if it wasn’t requesting a nonexistent character.

game.Players.PlayerRemoving:connect(function(player)
ds:SetAsync(player.UserId, player.Character.Humanoid.Health) -- all of this is broken.
end)

im trying to find a solution to it on the spot.

You could try recording the player’s health when it changes and store that, then when they leave retrieve the value’s data and delete it.

I’m not sure if CharacterRemoving works as they leave, but you could try it as an alternative to saving health on change. (If it does, of course, make sure you don’t update their health to 0 on join)

local Game = game
local Players = Game:GetService("Players")
local DataStoreService = Game:GetService("DataStoreService")
local HealthStore = DataStoreService:GetDataStore("HealthStore")

local Healths = {}

local function OnPlayerAdded(Player)
	local function OnCharacterAdded(Character)
		local function OnHumanoidHealthChanged(Health)
			Healths[Player] = Health
		end
		
		local Humanoid = Character:FindFirstChildOfClass("Humanoid") or Character:WaitForChild("Humanoid", 10)
		if Humanoid then Humanoid.HealthChanged:Connect(OnHumanoidHealthChanged) end
	end
	
	Player.CharacterAdded:Connect(OnCharacterAdded)
	
	local Success, Result = pcall(function() return HealthStore:GetAsync(Player.UserId) end)
	if not Success then warn(Result) return end
	if not Result then return end
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local Humanoid = Character:FindFirstChildOfClass("Humanoid") or Character:WaitForChild("Humanoid", 10)
	if Humanoid then Humanoid.Health = Result end
end

local function OnPlayerRemoving(Player)
	if not Healths[Player] then return end
	local Success, Result = pcall(function() return HealthStore:SetAsync(Player.UserId, Healths[Player]) end)
	if not Success then warn(Result) end
	Healths[Player] = nil
end

Players.PlayerAdded:Connect(OnPlayerAdded)
Players.PlayerRemoving:Connect(OnPlayerRemoving)

You may need to include ‘BindToClose’ for studio testing but this is working on my end.

1 Like