Hey guys, I have made a Stat Saving script (pretty basic), and would like to make it so it also autosaves player data every minute or so… what modifications should I make? Here is the full script:
local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")
local AUTOSAVE_INTERVAL = 60
local VIPid = 9456079
game.Players.PlayerAdded:Connect(function(player)
local character = player.Character
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Points = Instance.new("IntValue")
Points.Name = "Points"
Points.Parent = leaderstats
local Wins = Instance.new("IntValue")
Wins.Name = "Wins"
Wins.Parent = leaderstats
local Activations = Instance.new("IntValue")
Activations.Name = "Activations"
Activations.Parent = leaderstats
local Deaths = Instance.new("IntValue")
Deaths.Name = "Deaths"
Deaths.Parent = leaderstats
local Upgrades = Instance.new("Folder")
Upgrades.Name = "Upgrades"
Upgrades.Parent = player
local SpeedLevel = Instance.new("IntValue")
SpeedLevel.Name = "SpeedLevel"
SpeedLevel.Parent = Upgrades
local JumpLevel = Instance.new("IntValue")
JumpLevel.Name = "JumpLevel"
JumpLevel.Parent = Upgrades
local maxSpeed = Instance.new("IntValue")
maxSpeed.Name = "maxSpeed"
maxSpeed.Parent = player
local maxJump = Instance.new("IntValue")
maxJump.Name = "maxJump"
maxJump.Parent = player
local CurrentSpeed = Instance.new("IntValue")
CurrentSpeed.Name = "CurrentSpeed"
CurrentSpeed.Parent = player
local CurrentJump = Instance.new("IntValue")
CurrentJump.Name = "CurrentJump"
CurrentJump.Parent = player
local Multiplier = Instance.new("NumberValue")
Multiplier.Name = "Multiplier"
Multiplier.Parent = player
if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, VIPid) then
Multiplier.Value = 1.5
else
Multiplier.Value = 1
end
-->> Data: Begining
local playerUserId = "Player_"..player.UserId
-->>Data: Load Data
local data
local success, errormessage = pcall(function()
data = myDataStore:GetAsync(playerUserId)
end)
if success then
if data then
Points.Value = data.Points
Wins.Value = data.Wins
Activations.Value = data.Activations
Deaths.Value = data.Deaths
SpeedLevel.Value = data.SpeedLevel
JumpLevel.Value = data.JumpLevel
maxSpeed.Value = data.maxSpeed
maxJump.Value = data.maxJump
CurrentSpeed = data.CurrentSpeed
CurrentJump = data.CurrentJump
Multiplier = data.Multiplier
end
end
end)
-->> Data: Saving Stats
game.Players.PlayerRemoving:Connect(function(player)
local playerUserId = "Player_"..player.UserId
local data = {
Points = player.leaderstats.Points.Value;
Wins = player.leaderstats.Wins.Value;
Activations = player.leaderstats.Activations.Value;
Deaths = player.leaderstats.Deaths.Value;
SpeedLevel = player.Upgrades.SpeedLevel.Value;
JumpLevel = player.Upgrades.JumpLevel.Value;
maxSpeed = player.maxSpeed.Value;
maxJump = player.maxJump.Value;
CurrentSpeed = player.Character:FindFirstChild("Humanoid").WalkSpeed;
CurrentJump = player.Character:FindFirstChild("Humanoid").JumpPower;
Multiplier = player.Multiplier.Value;
}
local success, errormessage = pcall(function()
myDataStore:SetAsync(playerUserId, data)
end)
if success then
print("Data succefully saved!")
else
print("Data saving error")
warn(errormessage)
end
end)
I’ll tell you what to do. U need a Loop that waits 1 minute and everytime a Minute is passed. Loop trough all Players and Save their Data, U also want a longer wait time since u don’t want to throttle your DataStore
Doing this can cause data loss because of too many Async requests.
They cause data loss because every time you send a request, ROBLOX’s API has to process that request and execute what you want it to do. If you send too many requests, that is too many requests for ROBLOX’s API to handle which will cause it to throttle, and if you send even more, it will stop listening to your requests altogether, meaning no data will be saved at all.
I’d recommend switching to Datastore2, as @BindStep suggested.
I need to save player WalkSpeed and JumpPower, although that can’t be done when PlayerRemoving because their Humanoid doesn’t exist anymore, so saving it prior to that is the solution.
One way would be to use some sort of infinite loop,
while true do
-- loop through all players, saving all of their data individually
for _, player in ipairs(game:GetService("Players"):GetPlayers()) do
-- save data
wait(5) -- an interval between saving data, to prevent throttling requests
end
wait(60)
end
Thank you for your comment… This is my first ever “Heavy game” and this does not encourage. I have been scripting almost everyday for the past year now and am still learning. I know all the basics and the problem I have doesn’t happen to be basic. I just have a problem because rn my script doesn’t get PlayerUserId, whereas it did. Instead of making me feel bad for myself, help.
-- you already defined local function saveData in your script
local Players = game:GetService("Players")
while true do
for _, player in ipairs(Players:GetPlayers()) do
saveData(player)
wait(5) -- a delay between saving data for every player
end
wait(60) -- delay between each time the code in the while loop is to run
end
Your stat save script should be a function in itself and not just hardcoded into the PlayerAdded() function. This will help you in the long run when your scripts are pushing the hundreds or even thousands of lines and readability & comprehensiveness becomes a necessity.
Below is something similar that I use for DataStores:
local save_interval = 120 --roblox limits it to every 2 minutes so we'll roll with this
function SaveFunction(PLR)
coroutine.wrap(function() --wrapping it in a coroutine will allow the rest of the script to run after this is called
while true do
wait(save_interval)
-- do save logic here
end
end)()
end)
If you’re trying to save a humanoid’s walkspeed, you can simply have an IntValue inside of the player called “Walkspeed” and set that to the Humanoid’s walkspeed whenever it changes. Then, save that value on PlayerRemoving.