So I have a while loop running every (1) second for my time rewards system (this is based on the time you play so updating every sec) and I’m wondering if this can be bad for performance since i’ll have multiple players getting timeplayed value up every sec with a loop
If you doing it like
while true do
for _, player in pairs(Players:GetPlayers()) do
-- Add point
end
task.wait(1)
end
Then you’ll be fine, will not have any noticeable affect on performance
This can be done MUCH better. Try not to run for loops in a while loop:
game.Players.PlayerAdded:Connect(function(player)
while task.wait(1) do
-- Add point
end
end)
This is worse, for several reasons:
- This would run a new while loop every single time a player joins (1 million players join over time in a single server, you gonna have problems)
- Doing the wait inside the while do part is heavely frowned upon. Don’t do it, ever.
- There is nothing wrong with for loops in while loops. Can have dozens of for loops in a single while loop and have no issues
here is a way you can do it without loops
local times = {}
local rewardPerSecond = 10
local function ClaimReward(player)
local deltaTime = os.time() - times[player]
player.leaderstats.Coins.Value += deltaTime * rewardPerSecond
times[player] += deltaTime
end
game.Players.PlayerAdded:Connect(function(player)
-- save the time the player enters the game
times[player] = os.time()
end)
game.Players.PlayerRemoving:Connect(function(player)
ClaimReward(player)
-- remove the players time so we don't have a memory leak
times[player] = nil
end)
That would work but thats not my goal
whats your goal? because it can be modified
is this your goal?
-- server script
local times = {}
local rewardPerSecond = 10
local function GetPlayerCoins(player)
local deltaTime = os.time() - times[player]
return player.leaderstats.Coins.Value + deltaTime * rewardPerSecond
end
local function ClaimReward(player)
local deltaTime = os.time() - times[player]
player.leaderstats.Coins.Value += deltaTime * rewardPerSecond
times[player] += deltaTime
player.Reward.Value = times[player]
end
game.Players.PlayerAdded:Connect(function(player)
-- save the time the player enters the game
times[player] = os.time()
-- create a NumberValue so the player can see how many coins they have
local reward = Instance.new("NumberValue")
reward.Name = "Reward"
reward.Value = times[player]
reward.Parent = player
end)
game.Players.PlayerRemoving:Connect(function(player)
ClaimReward(player)
-- remove the players time so we don't have a memory leak
times[player] = nil
end)
-- localscript inside starterplayerscripts
local rewardPerSecond = 10
local reward = game.Players.LocalPlayer:WaitForChild("Reward")
while true do
local deltaTime = os.time() - reward.Value
print("Coins", player.leaderstats.Coins.Value + deltaTime * rewardPerSecond)
task.wait(1)
end
Basically I wanna save a value called “TimePlayed” and update it every second any good way to achieve this?
why do you want to update it every second instead of updating it only when you need to use it
Its “TimePlayed” so its recording how long you’ve played forever
ok ill show you how to save it into a datastore without a loop
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("Store")
local times = {}
local timePlayed = {}
local function GetCurrentPlayTime(player)
return timePlayed[player] + os.time() - times[player]
end
game.Players.PlayerAdded:Connect(function(player)
-- get the players play time from the datastore
local success, value = pcall(dataStore.GetAsync, dataStore, player.UserId)
-- datastore failed to load roblox datastore server might be down
if success == false then return end
-- set the current time
times[player] = os.time()
-- set the play time
timePlayed[player] = value or 0
end)
game.Players.PlayerRemoving:Connect(function(player)
-- the players datastore failed to load so this is now nil
if times[player] = nil then return end
-- work out how long the player has been playing
local deltaTime = os.time() - times[player]
-- add the delta time to the play time
timePlayed[player] += deltaTime
-- save the play time into the datastore
local success, value = pcall(dataStore.SetAsync, dataStore, player.UserId, timePlayed[player])
-- delete the values so we don't have a memory leak
times[player] = nil
timePlayed[player] = nil
end)
this is also more accurate then using
while true do
task.wait(1)
end
because task.wait does not wait exactly 1 second
you can find out more here