How to make an autosave every minute

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)
2 Likes

You shouldnt do this as it will cause dataloss because theres too many SetAsync requests

2 Likes

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

1 Like

You can’t do this, saving that much values from all players at the same time is going to make it throttle

1 Like

How much u Save data depends on the Amount of Players are in the game so thats not a problem

more info

Also i meant saving data for each player after each other not at the same time

1 Like

How could I fix that? And why do too many SetAsync requests cause dataloss? I also don’t think that I’m using too many Async requests.

1 Like

Consider using DataStore2

2 Likes

Here are the limits for DataStores. Take a look specifically at the Server Limits.

1 Like

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.

1 Like

Why do you even want it to auto save every minute?

1 Like

Based off of that, it should be plenty, and I’m perfectly fine…

1 Like

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.

1 Like

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
2 Likes

Try having a PropertyChangedSignal event and store the New Value somewhere. When the player leaves use that Value when Saving

1 Like

You shouldn’t really worry about data loss, it’s enough time to not throttle.

game.Players.PlayerAdded:Connect(function()
    coroutine.wrap(function()
        while true do
            wait(60)
            -- Save Data
        end
    end)
end)
1 Like

Ok, so this is what i came up with, although it says that it was unable to get PlayerUserId:

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

local function saveData(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

game.Players.PlayerRemoving:Connect(saveData)

while true do
	for _, player in ipairs(game:GetService("Players"):GetPlayers()) do
		saveData()
		wait(5)
	end
	wait(60)
end
2 Likes

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.

1 Like

just use that function saveData in a loop;

  -- 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
2 Likes

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)
4 Likes

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.