Well, I have made this system to save Healthy MaxHealth of the player’s humanoid, I put it for them to use (Free use). Well, the script works when the player enters, if it is the first time the player enters, it will give him 100 Health and MaxHealth. When exiting the game, the data is saved in the same PlayerAdded function, inside of that is the CharacterRemoving which is what saves the data when exiting, and when you die you get the health of MaxHealth (In case you make another script change the maxhealth, that amount of maxHealth you put to life). They can change the script, if you see any bug and fix it, let me know (This is what I could do, so I don’t think it’s professional).
local DataStore = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local HealthData = DataStore:GetDataStore("HealthData")
Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local Humanoid = char:WaitForChild("Humanoid")
Humanoid.Died:Connect(function()
local Get_Data_Died = {
Health = char.Humanoid.MaxHealth;
MaxHealth = char.Humanoid.MaxHealth;
}
local Success, err = pcall(function()
HealthData:SetAsync(plr.UserId, Get_Data_Died)
end)
end)
local Get_Data = nil
local Success, err = pcall(function()
Get_Data = HealthData:GetAsync(plr.UserId)
end)
if Success and Get_Data ~= nil then
if Get_Data.Health >= Get_Data.MaxHealth then
Humanoid.MaxHealth = Get_Data.MaxHealth
Humanoid.Health = Get_Data.MaxHealth
else
Humanoid.MaxHealth = Get_Data.MaxHealth
Humanoid.Health = Get_Data.Health
end
else
Humanoid.MaxHealth = 100
Humanoid.Health = 100
end
end)
plr.CharacterRemoving:Connect(function(char)
local Get_Data_Removing = {
Health = char.Humanoid.Health;
MaxHealth = char.Humanoid.MaxHealth;
}
local Success, err = pcall(function()
HealthData:SetAsync(plr.UserId, Get_Data_Removing)
end)
if Success then
print("Se ha guardado correctamente / Has been saved successfully")
else
print("hubo un error al guardar / there was an error saving")
warn(err)
end
end)
end)
You see, without that when you die and reappear, you get the same life you had before you died. I did it this way so that when I died, life would restart (sending a SetAsync with the MaxHealth data so that you have a lifetime depending on maxHealth)
I saw your script didn’t have cache, so… I added cache
New script with cache
local DataStore = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local HealthData = DataStore:GetDataStore("HealthData")
local cache_ = {}
Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
spawn(function()
while true do
if char:FindFirstChild("Humanoid") then
local Get_Data_Updated = {
Health = char.Humanoid.MaxHealth;
MaxHealth = char.Humanoid.MaxHealth;
}
cache_[plr.UserId] = Get_Data_Updated
task.wait(6)
end
end
end)
local Humanoid = char:WaitForChild("Humanoid")
Humanoid.Died:Connect(function()
local Get_Data_Died = {
Health = char.Humanoid.MaxHealth;
MaxHealth = char.Humanoid.MaxHealth;
}
cache_[plr.UserId] = Get_Data_Died
end)
local Get_Data = nil
local Success, err = pcall(function()
Get_Data = HealthData:GetAsync(plr.UserId)
end)
if Success and Get_Data ~= nil then
if Get_Data.Health >= Get_Data.MaxHealth then
Humanoid.MaxHealth = Get_Data.MaxHealth
Humanoid.Health = Get_Data.MaxHealth
else
Humanoid.MaxHealth = Get_Data.MaxHealth
Humanoid.Health = Get_Data.Health
end
else
Humanoid.MaxHealth = 100
Humanoid.Health = 100
end
end)
plr.CharacterRemoving:Connect(function(char)
local Get_Data_Removing = {
Health = cache_[plr.UserId].Health or 100;
MaxHealth = cache_[plr.UserId].MaxHealth or 100;
}
print(Get_Data_Removing)
local Success, err = pcall(function()
HealthData:SetAsync(plr.UserId, Get_Data_Removing)
end)
if Success then
print("Se ha guardado correctamente / Has been saved successfully")
else
print("hubo un error al guardar / there was an error saving")
warn(err)
end
task.wait(1)
cache_[plr.UserId] = nil
end)
end)
Certainly, I forget to answer as to whether the data is saved. If you save the data and load it, although there is also a small possibility of a warn that you are sending a lot of data (the probability is small)
Sorry, I was sleeping but, what I meant by caching is to save the health, max health player last had. If they got new ones we just simply erase the data before. So it should be the same as doing 1 normal SetAsync
It works fine but, I think it might cause a memory leak. You’re literally creating a while loop every time the character gets added, so more loops will get added as the player dies and respawns, causing huge lag.
Using a while loop with a 6-second interval isn’t very accurate, I’d suggest you use RunService.Heartbeat if you’re scared the character already gets removed the moment Players.CharacterRemoving fires, or just caching during Player.CharacterRemoving should work.
Also I’m not sure why you should get the data from the datastore every time the character is added. Shouldn’t you do that for only the first time, second time onwards use the values from the cache?
Can that help not to lose data? I have a player settings system (something like a game settings menu, like GTA 5 or Warzone), although the data is rarely lost, like this I thought caching might be the solution
The idea of caching is to save the data locally and finalizes it when the player leave, so no matter how many times they changed something, you only need to save once.
On the other side, if you keep saving when they changed something, it may cause data throttle and you might lose data.
All I’m going to say is this is alright. The simplicity in this is reasonable for any scripter with some advanced knowledge in Lua. I like how you’re using PCalls which are a good sign! Although, I feel like it isn’t very necessary. Just my opinion.