local DSService = game:GetService('DataStoreService'):GetDataStore('Stats') game.Players.PlayerAdded:connect(function(plr) repeat wait() until plr.Character local char = plr.Character local uniquekey = 'id-'..plr.userId if DSService:GetAsync(uniquekey) then plr.Leaderstats.Skillpoints.Value = DSService:GetAsync(uniquekey)[1] end plr.PlayerGui.Options.Frame.Save.MouseButton1Click:connect(function() DSService:SetAsync(uniquekey, plr.Leaderstats.Skillpoints.Value) plr.PlayerGui.Options.Frame.Save.Text = 'Saved' wait(2) plr.PlayerGui.Options.Frame.Save.Text = 'Save' end) end) -- end for playeradd function
This is a normal script so no it isn't localscript, Skillpoints is another value already made in inside the player in another script, and the GUI is just there to notify the players the data's been saved. the problem is it isn't loading when I rejoin?
In output, it also says ServerScriptService.Data:8: attempt to index a number value
There are a number of problems with your script.
WaitForChild
in that case (with a timeout in-case something goes wrong). Since you're accessing multiple children, it may be worth using the function I wrote below.pcall
as they may errorlocal DSService = game:GetService('DataStoreService'):GetDataStore('Stats') function WaitForChildren(obj, timeout, ...) local t = {...} for i = 1, #t do obj = obj:WaitForChild(t[i], timeout) if not obj then return nil end end return obj end game.Players.PlayerAdded:connect(function(plr) local skillpoints = WaitForChildren(plr, 5, "Leaderstats", "Skillpoints") --or could do "skillPoints = plr:WaitForChild("Leaderstats"):WaitForChild("Skillpoints")", but it wouldn't have a timeout if not skillpoints then print(plr, "did not receive Leaderstats.Skillpoints") return end local uniquekey = 'id-'..plr.userId --Uncomment the following line and its corresponding '--end))' if you want the player to be able to save immediately upon loading your game, even if the GetAsync errors. If it errors, this might mean that the datastores are down, so if you let the player save over it without first loading, they might lose the information stored there. Because of this, you might want to change what happens in the 'i == 5' code. --coroutine.resume(coroutine.create(function() local success, value for i = 1, 5 do --try 5x, once every 15 seconds success, value = pcall(function() return DSService:GetAsync(uniquekey) end) if success then break end if i == 5 then print("Could not retrieve data for", plr,", error message:", value) value = nil break end wait(15) end if value then skillpoints.Value = value end --end)) local save = WaitForChildren(plr, 5, "PlayerGui", "Options", "Frame", "Save") if save then local saveDB = false save.MouseButton1Click:connect(function() if saveDB then return end local success, errorMsg = pcall(function() DSService:SetAsync(uniquekey, skillpoints.Value) end) if success then save.Text = 'Saved' else save.Text = "Error: " .. errorMsg end saveDB = true wait(2) saveDB = false save.Text = 'Save' end) end end) -- end for playeradd function
I also recommend against allowing players to save every 2 seconds. Per player, you get a request every 6 seconds (and a few more for the server), meaning that it's only safe to save every 6 seconds on average (per player). Though, if you don't expect players to abuse this, it's probably okay.