How do I check if a player has been in a Region3 for some time and reset the timer if the player exits?

I have this region3 script that checks if the player is in a region3, but I don’t know how to setup a timer for how long the player has been in the Region3 and reset the timer if the player leaves.

local Reg = script.Parent
local pos1 = Reg.Reg1.Position
local pos2 = Reg.Reg2.Position
local region = Region3.new(pos1, pos2)

local players = {}
game:GetService("RunService").Heartbeat:Connect(function()
	local partsInRegion = workspace:FindPartsInRegion3(region, nil, 1000)
	for _,part in pairs(partsInRegion) do
		if part.Parent:FindFirstChild("Humanoid") then
			local plr = game.Players:FindFirstChild(part.Parent.Name)
			table.insert(players, plr)
		end
	end
	players = {}
end)
2 Likes

Just an idea:
You could store a table with each player and the time they’re in the region. Like so:

local playerTimes = {}


-- Player enters a region
do
    playerTimes[player] = os.time() -- Or something else
end

-- Find out how long they have been there
do
    local timeInit = playerTimes[player]
    local timePassed = if timeInit then os.time() - timeInit else 0
    print(`Time Passed: {timePassed}`)
end

-- Reset the timer to nil
do
    playerTimes[player] = nil
end

If you want the timer to still count after they exit, instead of staying stopped, use the same code as the “player enters a region” code instead.

It looks like I reset the player and put it back each loop (in line “players = {}” in the Heartbeat loop)
which caused some problems.

Any way to reset the “i” variable when the player isn’t in the Region3?

local Reg = script.Parent
local pos1 = Reg.Reg1.Position
local pos2 = Reg.Reg2.Position
local region = Region3.new(pos1, pos2)

local players = {}
local InRegion = false
local i = 0

game:GetService("RunService").Heartbeat:Connect(function()
	local partsInRegion = workspace:FindPartsInRegion3(region, nil, 1000)
	for _,part in pairs(partsInRegion) do
		if part.Parent:FindFirstChild("Humanoid") then
			local plr = game.Players:FindFirstChild(part.Parent.Name)
			table.insert(players, plr)
			InRegion = true
		end
	end
end)

while task.wait() do
	if InRegion then
		InRegion = false
		i += 1
		print(i)
		task.wait(1)
	end
end

I finally managed to get the hang of it. An easy way to count IF the player is inside a region3 and reset the timer if the player goes away is:

while task.wait() do
	if InRegion then
		InRegion = false
		i += 1
		print(i)
		task.wait(1)
	else
		i = 0
		print(i)
	end
	
	if i >= 120 then
		-- 2 mins
	end
end

So in the end, the script looks like this:

local Reg = script.Parent
local pos1 = Reg.Reg1.Position
local pos2 = Reg.Reg2.Position
local region = Region3.new(pos1, pos2)

local plr = nil
local players = {}
local InRegion = false
local i = 0

game:GetService("RunService").Heartbeat:Connect(function()
	local partsInRegion = workspace:FindPartsInRegion3(region, nil, 1000)
	for _,part in pairs(partsInRegion) do
		if part.Parent:FindFirstChild("Humanoid") then
			plr = game.Players:FindFirstChild(part.Parent.Name)
			table.insert(players, plr)
			InRegion = true
		end
	end
end)

while task.wait() do
	if InRegion then
		InRegion = false
		i += 1
		print(i)
		task.wait(1)
	else
		i = 0
		print(i)
	end
	
	if i >= 120 then
		-- 2 mins
	end
end

if There’s a better way, please tell me!

Before I answer with my response, is this a localscript or a server script? Because if it’s the latter, then your script won’t work for more than one player.

I intend to make this a 1 player game, so it doesn’t matter either way. It is, however, a ServerScript.

I see,
In general, it is advised to make it work for any number of players as you do not know if you’re going to expand or reuse code in the future.

Anyway, I would first check if the player is in the region every time the player moves rather than all the time.

Performing a check on Heartbeat can consume resources and it is certain that the player cannot go in or out of a region withour moving.

Consider the following code.

local Players = game:GetService("Players")
local player = Players:GetPlayers()[1]

player.CharacterAdded:Connect(function(char)
    local rootPart = char.HumanoidRootPart or char:WaitForChild("HumanoidRootPart")
    rootPart:GetPropertyChangedSignal("CFrame"):Connect(checkRegion)
    
end)

function checkRegion()
    if get parts in region parent == player.character then .........
end

EDIT: Another thing you can do is create an invisible part around the region and detect if the player touches it or exits it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.