Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

DataStore isn't loading the stat?

Asked by 8 years ago
01local DSService = game:GetService('DataStoreService'):GetDataStore('Stats')
02game.Players.PlayerAdded:connect(function(plr)
03repeat wait() until plr.Character
04local char = plr.Character
05local uniquekey = 'id-'..plr.userId
06 
07    if DSService:GetAsync(uniquekey) then
08        plr.Leaderstats.Skillpoints.Value = DSService:GetAsync(uniquekey)[1]
09    end
10 
11 
12plr.PlayerGui.Options.Frame.Save.MouseButton1Click:connect(function()
13    DSService:SetAsync(uniquekey, plr.Leaderstats.Skillpoints.Value)
14    plr.PlayerGui.Options.Frame.Save.Text = 'Saved'
15    wait(2)
View all 22 lines...

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

0
Because you're not saving it as a table. Just do DSService:GetAsync(uniquekey) and see if that works. User#14829 0 — 8y
0
Thanks! it works now, however the script loads too fast to the point where the making of the values in the other script are slow, and when it says "Leaderstats is not apart of Player" but I just added a wait(10) above the GetAsync thing and now it works fine. Is there a better way for it to wait? HornedWyven 10 — 8y

1 answer

Log in to vote
0
Answered by 8 years ago

There are a number of problems with your script.

  • You do not use the player's character, but wait for it anyway
  • You do not wait for the leaderboard script to insert the "Leaderstats" object into the player. You should use 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.
  • You call GetAsync twice unnecessarily. You should assign the result to a variable so you only need to call GetAsync once.
  • You do not implement debounce on the save feature. A person could rapidly click to save repeatedly, wasting your server's requests.
  • You must put datastore commands in pcall as they may error
01local DSService = game:GetService('DataStoreService'):GetDataStore('Stats')
02function WaitForChildren(obj, timeout, ...)
03    local t = {...}
04    for i = 1, #t do
05        obj = obj:WaitForChild(t[i], timeout)
06        if not obj then return nil end
07    end
08    return obj
09end
10game.Players.PlayerAdded:connect(function(plr)
11    local skillpoints = WaitForChildren(plr, 5, "Leaderstats", "Skillpoints")
12    --or could do "skillPoints = plr:WaitForChild("Leaderstats"):WaitForChild("Skillpoints")", but it wouldn't have a timeout
13    if not skillpoints then print(plr, "did not receive Leaderstats.Skillpoints") return end
14    local uniquekey = 'id-'..plr.userId
15    --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.
View all 52 lines...

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.

Ad

Answer this question