You don’t need to count the seconds as the computer already does it for you. On Roblox you can use UNIX timestamp, which is the amount of seconds that have elapsed since 00:00:00 UTC on 1 January 1970. You can obtain a UNIX timestamp by using the built-in library os and calling its time method.
print(os.time()) -- 1714940821
-- 1 second later
print(os.time()) -- 1714940822
-- To obtain the elapsed time
print(1714940822 - 1714940821) -- 1
Now using this method you can obtain the amount of seconds player has been playing your game. When player joins your game you want to obtain the timestamp, and once the player leaves the game, you will want to obtain another timestamp and subtract the first timestamp from the newer one to obtain the amount of seconds that the player has been in your game.
local Players = game:GetService("Players")
local join_time: { [Player]: number } = {}
local function player_joined(player: Player)
join_time[player] = os.time()
end
local function player_leaving(player: Player)
if join_time[player] then
local elapsed = os.time() - join_time[player]
print(`{player.Name} has played the game for {elapsed} seconds`)
join_time[player] = nil -- Cleanup, or there will be a memory leak!
end
end
for _, player in Players:GetPlayers() do
player_joined(player)
end
Players.PlayerAdded:Connect(player_joined)
Players.PlayerRemoving:Connect(player_leaving)
Now all you need to do is update the amount of seconds that the player has played your game for. There is many ways to save data, but for the sake of simplicity of this guide, I will show the simplest method. When player joins we will read their play time for debugging purposes, we might get nil which means that the key doesn’t exist, so player never had their play time recorded and we will treat it as 0. When player leaves, we will take their elapsed time, and add it to their total elapsed time which is saved in the data store, we will achieve this by using IncrementAsync method.
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local play_time_store = DataStoreService:GetDataStore("play_time")
local join_time: { [Player]: number } = {}
local function save_play_time(player: Player, elapsed: number)
local success = pcall(function()
play_time_store:IncrementAsync(tostring(player.UserId), elapsed, { player.UserId })
end)
if success then
print(`Successfully saved {player.Name}'s play time`);
else
warn(`Failed to save {player.Name}'s play time`)
end
end
local function read_play_time(player: Player): number?
local success, data = pcall(function()
return play_time_store:GetAsync(tostring(player.UserId))
end)
if success then
-- If data is nil, that means the key doesn't exist
-- if the key doesn't exist, the player's play time will be 0
return if data == nil then 0 else data
end
return
end
local function player_joined(player: Player)
join_time[player] = os.time()
local play_time = read_play_time(player)
if play_time then
print(`{player.Name} has play time of {play_time} seconds`)
else
warn(`Failed to read {player.Name}'s play time`)
end
end
local function player_leaving(player: Player)
if join_time[player] then
local elapsed = os.time() - join_time[player]
print(`{player.Name} has played the game for {elapsed} seconds`)
save_play_time(player, elapsed)
join_time[player] = nil -- Cleanup, or there will be a memory leak!
end
end
for _, player in Players:GetPlayers() do
player_joined(player)
end
Players.PlayerAdded:Connect(player_joined)
Players.PlayerRemoving:Connect(player_leaving)
This is what you will see in your output window when you join for the first time, and leave:
Daw588 has play time of 0 seconds
Daw588 has played the game for 2 seconds
Successfully saved Daw588's play time
When you join again, and leave, this is what you will see:
Daw588 has play time of 2 seconds
Daw588 has played the game for 3 seconds
Successfully saved Daw588's play time
All we are doing essentially boils down to this:
local play_time = 0
local function simulate_session()
local join_time = os.time()
task.wait(math.random(1, 3))
local leave_time = os.time()
local elapsed = leave_time - join_time
play_time += elapsed
end
-- First session
simulate_session()
print(play_time) -- 1
-- Second session
simulate_session()
print(play_time) -- 4
-- Third session
simulate_session()
print(play_time) -- 7
One last thing: If you want to display minutes to the player, you can convert seconds to minutes.
local play_time = 120 -- 120 seconds
-- Note: We are using math.floor to get rid of decimals because some numbers will produce non integer result
-- Note: There is 60 seconds in one minute
local minutes = math.floor(play_time / 60) -- 2 minutes
print(minutes) -- 2
This should get you started on the developing your play time saving feature. One thing to note is that the data saving solution is very simple and doesn’t account for situations when server crashes, or when player joins another server while their data is still saving in the previous one. Those situations can cause data loss! You will need to implement mechanisms like periodical data saves, and session locking. Though I wouldn’t recommend writing such system yourself, instead you should choose a battle tested data store solutions like DataStore2, and ProfileService.