So I have a folder in my workspace, and in the folder there are parts that I want to check when players entered them, and check when they left.
that’s how I did it:
local Players = game:GetService("Players")
local PartsToCheck = workspace.Parts:GetChildren()
local function CheckIfFoundPlayer(partToCheck)
local plrsInside = {}
local oldPlayers = {}
local parts, plr
while wait() do
-- get parts inside part
parts = workspace:GetPartsInPart(partToCheck)
-- check if parts are parts of players
for i, v in pairs(parts) do
if v.Parent:FindFirstChild("Humanoid") then
plr = Players:GetPlayerFromCharacter(v.Parent)
if not table.find(plrsInside, plr) then
if not table.find(oldPlayers, plr) then -- not found in old list, means it's new player that entered
print(plr.Name .. " Has Entered")
end
table.insert(plrsInside, plr)
end
end
end
-- check if players left
for i, v in pairs(oldPlayers) do
if not table.find(plrsInside, v) then
print(v.Name .. " Has left")
table.remove(oldPlayers, i)
end
end
-- add new players to the old table
for i, v in pairs(plrsInside) do
if not table.find(oldPlayers, v) then
table.insert(oldPlayers, v)
end
end
table.clear(plrsInside) -- clean to start finding new
end
end
for i, v in pairs(PartsToCheck) do
coroutine.wrap(CheckIfFoundPlayer)(v)
end
Question is, will that make any performance issues if there are a lot parts in the folder? is there a way to make it better? (btw touched event is really buggy, that’s why i don’t use that.)
wdym? region3 is basically doing the same thing I made but with more steps. you have to create a region3 variable first, setting it’s vectors and only then calling Workspace:FindPartsInRegion3(region3). And that’s instead just calling workspace:GetPartsInPart(partToCheck) which is what I did.
local Players = game:GetService("Players")
local PartsToCheck = workspace.Parts:GetChildren()
local function isInsideBrick(position, brick)
local v3 = brick.CFrame:PointToObjectSpace(position)
return (math.abs(v3.X) <= brick.Size.X / 2)
and (math.abs(v3.Y) <= brick.Size.Y / 2)
and (math.abs(v3.Z) <= brick.Size.Z / 2)
end
local function GetAllPlayersInsidePart(playersAlreadyInside, part)
local list = {}
for _, player in ipairs(Players:GetPlayers()) do
if player.Character then
local torso = player.Character:FindFirstChild("HumanoidRootPart")
if torso and isInsideBrick(torso.Position, part) then
table.insert(list, player)
end
end
end
return list
end
local function CheckNewPlayersInside(oldTable, newTable)
for i, v in pairs(newTable) do
if not table.find(oldTable, v) then
print(v.Name .. " Entered")
end
end
end
local function CheckPlayersLeft(oldTable, newTable)
for i, v in pairs(oldTable) do
if not table.find(newTable, v) then
print(v.Name .. " Has left")
end
end
end
local function CheckIfFoundPlayer(partToCheck)
local plrsInside = {}
local oldPlayers = {}
local parts, plr
while wait() do
-- get players inside
plrsInside = GetAllPlayersInsidePart(oldPlayers, partToCheck)
-- check players entered
CheckNewPlayersInside(oldPlayers, plrsInside)
-- check players left
CheckPlayersLeft(oldPlayers, plrsInside)
-- replace old with new
oldPlayers = plrsInside
end
end
for i, v in pairs(PartsToCheck) do
coroutine.wrap(CheckIfFoundPlayer)(v)
end
also do I have to worry about creating a new coroutine for each part?