I am currently trying to decide on the best way to track how many minutes the players have played the game. I’ve got 2 ways of doing this and i am not sure which is better. Keep in mind that the game will have a max of 50-75 players per server.
my first solution is a simple while player loop that would wait 60 seconds before adding 1 minute
(WaitCalculator is a module that replaces wait() function)
--first solution
Players.PlayerAdded:Connect(function(player)
local Minutes = player:WaitForChild("leaderstats").Minutes
while Players:FindFirstChild(player.Name) do
WaitCalculator(60)
Minutes.Value += 1
end
end)
my second solution is to have a table of all players that tracks their seconds, adding 1 to each currently online player and then adding 1 minute when they gather 60 seconds
--second solution
local PlayerSeconds = {}
Players.PlayerAdded:Connect(function(player)
PlayerSeconds[player.Name] = 0
end)
Players.PlayerRemoving:Connect(function(player)
PlayerSeconds[player.Name] = nil
end)
while true do
for i,v in pairs(PlayerSeconds) do
v += 1
if v == 60 then
Players:FindFirstChild(v):WaitForChild("leaderstats").Minutes.Value += 1
v = 0
end
end
WaitCalculator(1)
end
Perhaps you know of an even better way of doing this, if so i’d be grateful if you shared it with me.
Yep like @CrazySnoopylove said os.time() is so much better because it offers an event based approach where code runs at required controllable times rather than polling where the code runs continuously no matter what happens. While wait() do is notorious for promoting this practice although you can say if it works it works.
Here is a service style module thanks to Sleitnick for teaching me this style of coding from aero game framework to get the players time only when the function runs which should be on the server or you can implement a remote event method sync to sync the join times on client and server.
-- Player Time Service Module
-- Dthecoolest
-- March 17, 2021
local Players = game:GetService("Players")
local PlayerTimeService = {}
local PlayerJoinTimeDictionary = {}
PlayerTimeService.PlayerJoinTimeDictionary = PlayerJoinTimeDictionary
local function onJoin(player)
PlayerJoinTimeDictionary[player] = os.clock()
end
Players.PlayerAdded:Connect(onJoin)
for _, player in pairs(Players:GetPlayers()) do
coroutine.wrap(function()
onJoin(player)
end)()
end
Players.PlayerRemoving:Connect(function(player)
PlayerJoinTimeDictionary[player] = nil
end)
function PlayerTimeService:GetPlayerTimePlayedInCurrentGame(player: Player)
local playerJoinTime = self.PlayerJoinTimeDictionary[player]
local timeElapsedSinceFirstJoin = os.clock() - playerJoinTime
return timeElapsedSinceFirstJoin
end
return PlayerTimeService
Add the value by whatever delta time wait(1) yields for and convert it to minutes.
Players.PlayerAdded:Connect(function(player
local Minutes = player:WaitForChild("leaderstats").Minutes
while player:IsDescendantOf(game) do
Minutes.Value += wait(60) / 60
end
end)
game.Players.PlayerAdded:Connect(function(plr)
local timeByMinute = plr:WaitForChild("leaderstats").Time
local minute = 60
local char = plr.Character
wait(minute)
timeByMinute.Value = timeByMinute.Value + 1
repeat until char == nil
end
end)
end
why use a module for this? Isn’t a single server script more than sufficient for the whole code? More importantly, how and under what conditions do you require this module? What did you put in the server script that requires it?
The usage of a module is so that any script can read the PlayerJoinTimeDictionary, so you can have a script like a weapons giver script read it, or a round manager script get the player join times.
These scripts will both require this module and use the PlayerTimeService:GetPlayerTimePlayedInCurrentGame function to do stuff like check the time the moment a gui is popped up to allow the player to purchase a weapon.
Moreover, os.clock() is accurate as well. However you can still use the wait(n) approach just make sure the use the delta time wait(n) returns cuz it might wait 60.14 seconds, even RunService:HeartBeat:Wait() is no exception to this issue.
I’ve never encountered delta time, i’ll look into it. However I do not use wait() i use
the fast wait module made by CloneTrooper. I can’t claim to fully understand it but some of the best programmers in the community recommend it and i’ve been using it without any issues for a long time now. I am hoping in the end my original solution will suffice then.
You can store the timestamp they join the game using os.time() and subtract it from the current timestamp when they leave. To get their play time while playing, just subtract their join time from the current timestamp. You could do this on a loop using the RunService events.