Trying To Detect When The Rootpart of a Player Leaves a Certain Zone

Hello,
So I’m trying to make a zone system using UserId’s to detect when a player is in a zone or not and ease of use with checking for it with other scripts.

And it functions properly, I just have no idea how to detect when the rootpart of said player is no longer in the part.

:GetPlayerByUserId(id).Character?

Here’s the script:

local zoneFolder = workspace.Zones

local zone = {}

zone.Zones = {}

-- make a table iteration for every zonepart that exists
function zone:indexZones()
	for _, zonePart in pairs(zoneFolder:GetChildren()) do
		if not zonePart:IsA("BasePart") then return warn("zonePart", tostring(zonePart), "Doesn't Exist.") end

		self.Zones[zonePart.Name] = {}
	end
end

function zone:updateZones(plr)
	for _, zonePart in pairs(zoneFolder:GetChildren()) do		
		local boundBox = workspace:GetPartsInPart(zonePart)

		for _, partInBox in pairs(boundBox) do
			if partInBox.Name == "HumanoidRootPart" then
				local player = game:GetService("Players"):GetPlayerFromCharacter(partInBox.Parent)

				if player then
					self.Zones[zonePart.Name] = {
						player.UserId
					}
				end



				end
			end
		end
	end
end

return zone

Any help is greatly appreciated! If you need more info, Don’t hesitate to ask!

You can detect if player isn’t inside the zone anymore like this:

function zone:updateZones(plr)
	for _, zonePart in pairs(zoneFolder:GetChildren()) do		
		local boundBox = workspace:GetPartsInPart(zonePart)
		local playersInside = self.Zones[zonePart.Name] -- stores players in zone last time the function was called
		self.Zones[zonePart.Name] = {} -- clears table
		for _, partInBox in pairs(boundBox) do
			if partInBox.Name == "HumanoidRootPart" then
				local player = game:GetService("Players"):GetPlayerFromCharacter(partInBox.Parent)

				if player then
					table.insert(self.Zones[zonePart.Name], player.UserId) 
					-- works with multiple players in zone
				end
			end
		end
		for _,newPlr in pairs(playersInside) do-- check if any player left the zone
			if not table.find(self.Zones[zonePart.Name], newPlr) then
				print(newPlr.."has left "..zonePart.Name) -- player left zone
			end
		end
	end
end

You could use the Touched and TouchEnded events of the BasePart class, which are fired when a part starts and stops touching another part, respectively.

Try this>>

local zoneFolder = workspace.Zones

local zone = {}

zone.Zones = {}

function zone:indexZones()
	for _, zonePart in pairs(zoneFolder:GetChildren()) do
		if not zonePart:IsA("BasePart") then return warn("zonePart", tostring(zonePart), "Doesn't Exist.") end

		self.Zones[zonePart.Name] = {}

		zonePart.Touched:Connect(function(hit)
			local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
			if player then
				self.Zones[zonePart.Name][player.UserId] = true
			end
		end)

		zonePart.TouchEnded:Connect(function(hit)
			local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
			if player then
				self.Zones[zonePart.Name][player.UserId] = nil
			end
		end)
	end
end

return zone