Instead of saving all values seperately you can better add them to a table and save the table only then you shouldnt have the problem
local PlayerData = {}
local Datastore = game:GetService("DataStoreService")
local Datakey1 = 640725830
local Datastore1 = Datastore:GetDataStore(Datakey1)
game.Players.PlayerAdded:Connect(function(plr)
for _, folder in pairs(script.Datastores:GetDescendants()) do
if folder:IsA('Folder') then
local v = folder:Clone()
v.Parent = plr
PlayerData[plr] = {}
for _, value in ipairs(v:GetDescendants()) do
if value.ClassName:match('Value') then
value.Value = Datastore1:GetAsync(plr.UserId,value.Name) or 0
PlayerData[plr][value.Name] = value.Value
value.Changed:Connect(function()
PlayerData[plr][value.Name] = value.Value
end)
end
end
Datastore1:SetAsync(plr.UserId, PlayerData[plr])
end
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
Datastore1:SetAsync(plr.UserId,PlayerData[plr])
PlayerData[plr] = nil
end)
This works fine for me it changes the value when you change it Example: Player.Boosters.Boost1 = 100 then you rejoin then it will set the boost1 to 100 here is the code and the issue about the datastore queue has been fixed too! enjoy!
local PlayerData = {}
local Datastore = game:GetService("DataStoreService")
local Datakey1 = 640725830
local Datastore1 = Datastore:GetDataStore(Datakey1)
game.Players.PlayerAdded:Connect(function(plr)
for _, folder in pairs(script.Datastores:GetDescendants()) do
if folder:IsA('Folder') then
local Header = folder:Clone()
Header.Parent = plr
PlayerData[plr] = {}
local Data = Datastore1:GetAsync(plr.UserId)
for _, value in pairs(Header:GetDescendants()) do
if value.ClassName:match('Value') then
value.Value = Data and Data[value.Name] or 0
PlayerData[plr][value.Name] = value.Value
value.Changed:Connect(function()
PlayerData[plr][value.Name] = value.Value
end)
end
end
--Datastore1:SetAsync(plr.UserId,PlayerData[plr])
end
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
Datastore1:SetAsync(plr.UserId,PlayerData[plr])
PlayerData[plr] = nil
end)
It always worked for me tho it works fine for values and never had any problem with it and nobody ever complained about data loss so xd but you can be right not sure tho I used changed already for like 5 years
Yeah guess it depends what people like to use tho if changed was really bad than roblox had removed it but you’re welcome feel free to change whatever you want if you need more help just let me know
OOOOOOOHHH, GetPropertyChangedSignal() only fires when a property is changed! It was underneath our noses the whole time . Thank you for helping me with my datastore script! I can’t believe how naive I just was! (does naive work in this context?)
It is fine I am glad I could help I wish you good luck with your project I only used GetPropertyChangedSignal for like example knowing if the visible property is changed of an UI. So good luck on your development journery
Use Changed for ValueObjects, not GetPropertyChangedSignal. Changed for ValueObjects is specially designed to fire when only the value changes and it is called with the new value as a parameter. GetPropertyChangedSignal is for other instances when needing granular change check control. It is also slightly slower because it is a callback, not a direct member of the instance.
Yeah that is exactly how I thought it was I just checked it it is also the way I work thanks tho and I think many people will appreciate your tutorial! Keep up the good work!
I’m just now realising that the stats reset on me…
Kept the same way (i think)
local Datastore = game:GetService("DataStoreService")
local Datakey1 = 640725831
local Datastore1 = Datastore:GetDataStore(Datakey1)
game.Players.PlayerAdded:Connect(function(plr)
for _, folder in pairs(script.Datastores:GetDescendants()) do
if folder:IsA('Folder') then
local Header = folder:Clone()
Header.Parent = plr
PlayerData[plr] = {}
local Data = Datastore1:GetAsync(plr.UserId)
for _, value in pairs(Header:GetDescendants()) do
if value.ClassName:match('Value') then
value.Value = Data and Data[value.Name] or 0
PlayerData[plr][value.Name] = value.Value
if value.Name:match('Booster') and value.Value < 1 then
value.Value = 1
end
value.Changed:Connect(function()
PlayerData[plr][value.Name] = value.Value
end)
end
end
--Datastore1:SetAsync(plr.UserId,PlayerData[plr])
end
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
Datastore1:SetAsync(plr.UserId,PlayerData[plr])
end)
Its alright if SetAsync doesnt work good enough I suggest you use UpdateAsync it works much better than SetAsync in my opinion SetAsync overwrites data and can cause sometimes data loss but UpdateAsync just updates the data so it will just update the data and not overwrite it.
Hope this will help and you can always send me if you need me
PS: it can also be helpfull to wrap the GetASync in a pcall to check if the code works without errors and so you can also check if the data gets returned
If you don’t have an advanced knowledge of cacheing, I would recommend using something like DataStore2 that can handle all of that for you for absolute security. I work with SQL all the time for production environments, and DataStore just has too many problems that I’d rather just do it with
DS2 than write massive cacheing and backup methods.