How to count the amount of time a player has been AFK

Hey so I have this simple thing that I want to add to my player overhead but I had some issues figuring out how to effectively do it.

I’m using UserInputService to detect whether the player is WindowFocused or not.

My main question is how can I manage to count the amount of time the player has been AFK for & display the amount of time in 00:00. What is the best possible way to accomplish this?

Code below.

Server

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local afkEvent = Instance.new("RemoteEvent")
afkEvent.Name = "AfkEvent"
afkEvent.Parent = ReplicatedStorage

local function setAfk(player, afk)
	local overhead = player.Character:WaitForChild("HumanoidRootPart"):WaitForChild("OverheadGui")
	local overheadText = overhead.Background:WaitForChild("AFK")
	if afk then
		overheadText.Visible = true
	else
		overheadText.Visible = false
	end
end

afkEvent.OnServerEvent:Connect(setAfk)



Client

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local afkEvent = ReplicatedStorage:WaitForChild("AfkEvent")

local function focusGained()
	afkEvent:FireServer(false)
end

local function FocusedReleased()
	afkEvent:FireServer(true)
end

UserInputService.WindowFocused:Connect(focusGained)
UserInputService.WindowFocusReleased:Connect(FocusedReleased)

As of right now only shows AFK text when you’re not windowfocused.
image

1 Like

You can use tick() for time and os.date to format the seconds you got into 00:00:00. I couldn’t find anything that could turn it into 00:00 instead.
For the format strings, use this documentation and scroll down to os.date: os | Roblox Creator Documentation

Like this:

local function AFKOn()
    local StartTime = tick()
end

local function AFKOff()
    local FinishTime = os.date("%X", StartTime - tick())
    return FinishTime
end

For checking if the user is AFK or not, you could probably use task.delay to run a function every few seconds and then check if the position of the character has always been same or not, I came up with this script, let me know if it works or not:

--[[ Server Script in StarterCharacterScripts, 
as you can get the character then and do everything on the server 
instead of the client
--]]

local Players = game:GetService("Players")

local Character = script.Parent -- The script is parented under the character when the player joins
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

local LatestPosition = nil -- we log the latest hrp position in the variable
local DelayBetweenRuns = 10 --seconds

local Runs = 0 -- how many times the function has ran
local AFK = false -- is afk or not

local function CheckForIdle()
	if LatestPosition ~= nil then
		if (HumanoidRootPart.Position - LatestPosition).Magnitude > 5 then -- if latest position greatly differs from current position, then afk is set to false
			AFK = false
			Runs = 0
			return CheckForIdle -- terminate function
		end
	end
	LatestPosition = HumanoidRootPart.Position
	Runs += 1
	
	if Runs >= 2 then -- if how many times the function has been ran is more than 2 and player has still not moved then afk is set to true
		AFK = true
	end
end

task.delay(DelayBetweenRuns, CheckForIdle)

Interesting way to check if a Player is idle, I understand exactly what you’re doing in the CheckForIdle function.

local function AFKOn()
    local StartTime = tick()
end

local function AFKOff()
    local FinishTime = os.date("%X", StartTime - tick())
    return FinishTime
end

Do I just call these functions in the if statements of the CheckForIdle so when the Player isn’t moving we’d call AFKOn there and then the opposite for AFKOff?

couldnt you detect inputs using UIS.InputBegan? instead of spam checking if the humanoid moved, (small example case) but what if the humanoid is on a moving brick?

When the window loses focus, set the variable startAFK to tick(). When the window is focused, set the same variable to zero. Now every render step, get the time spent being afk like this: startAFK == 0 and 0 or tick() - startAFK

I thought of that as well but I couldn’t figure out the logic for that code, I guess he could do the same thing I did but with .InputBegan.