Is there a better method for finding players in a certain area?

Currently, I am using a region to give a ForceField to players in the region, as well as remove it when they leave the region. I was wondering if there was another method or a more efficient way of doing this, because it currently updates the players ForceField with a small delay, despite me using Heartbeat. The only other idea I have is checking for the entire player rather than just the HumanoidRootPart, but the method I thought of would be very messy and probably not worth it in the end. Another thing I noticed is when I am jumping out of the region, it does not remove the ForceField until I am close to the ground.

local regionPart = workspace:WaitForChild("RegionPart")
local region = Region3.new(regionPart.Position - (regionPart.Size / 2), regionPart.Position + (regionPart.Size / 2))

local playersInRegion = {}

while true do
	local partsInRegion = workspace:FindPartsInRegion3(region, nil, math.huge)
	
	for _, part in ipairs(partsInRegion) do
		if part.Parent:FindFirstChild("Humanoid") then
			local playerFromPart = game:GetService("Players"):GetPlayerFromCharacter(part.Parent)
			
			if not table.find(playersInRegion, playerFromPart) then
				table.insert(playersInRegion, playerFromPart)
				local forceField = Instance.new("ForceField", playerFromPart.Character)
			end
		end
		
		for playerIndex, player in ipairs(playersInRegion) do
			if not table.find(partsInRegion, player.Character:FindFirstChild("HumanoidRootPart")) then
				table.remove(playersInRegion, playerIndex)
				player.Character:FindFirstChild("ForceField"):Destroy()
			end
		end
	end
	
	game:GetService("RunService").Heartbeat:Wait()
end
1 Like

You could try making an invisible part and use the Touched event. Simplest solution I can think of.

1 Like

This is what I came up with using your suggestion and it works quite well, it removes the ForceField very quickly but now gives one slower as opposed to using a region. I might just stick with this because it only runs when the part is touched, rather than once every heartbeat using the region.

local parent = script.Parent

parent.Touched:Connect(function(part)
	if part.Parent:FindFirstChild("Humanoid") then
		if part == part.Parent.PrimaryPart then
			local forceField = Instance.new("ForceField", part.Parent)
		end
	end
end)

parent.TouchEnded:Connect(function(part)
	if part.Parent:FindFirstChild("Humanoid") then
		if part == part.Parent.PrimaryPart then
			part.Parent:FindFirstChild("ForceField"):Destroy()
		end
	end
end)

Select players in the circle

We have a given Radius = 50

We put a BoolValue in every player that is false if he is outside the circle and true if he is inside the circle

This BoolValue when placed inside a StarterPlayer in StarterCharacterScripts

Make the name of the BoolValue “InsideValue”

We define the center of the circle, for example Pillar

This code when placed inside a ServerScriptService

while true do
wait()
	
local Radius = 50	
local Pillar = game.Workspace:WaitForChild("Pillar")
	
local children = workspace:GetChildren()
for i = 1, #children do
	local humanoid = children[i]:FindFirstChild("Humanoid")		
	local root = children[i]:FindFirstChild("HumanoidRootPart")
	if root ~= nil and humanoid ~= nil and humanoid.Health > 0 then	
	local Distance = (root.Position - Pillar.Position).magnitude		
	print(Distance)		
				
	if Distance <= Radius then		
	local character	= game.Workspace:FindFirstChild(children[i].Name)		
	    if character then			
	    local InsideValue = character:FindFirstChild("InsideValue")			
	        if InsideValue then		
	           InsideValue.Value = true
	        end				
	    end				
				
	else			
	local character	= game.Workspace:FindFirstChild(children[i].Name)		
	    if character then			
	    local InsideValue = character:FindFirstChild("InsideValue")			
	        if InsideValue then	
	           InsideValue.Value = false
	        end				
	    end						
	end			
	end
		
end		
end

Writing the note next to the trigger is not in the code

I wish you good luck in what you do