How do I find all players and make sure none are in an area

I have a respawning crate, that when broken, respawns (obviously) So I need to get all characters in the game, and make sure none of them are within 10 studs of the crate. (so the crate doesn’t spawn on them) I have some code, but not enough - my code -

local PlrCount = nil
for i, plr in ipairs(game.Players:GetChildren()) do
PlrCount += 1
			local Character = plr.Character
			local position = Character.HumanoidRootPart.Position - script.Parent.MainOrigin.Position
			local magnitude = position.magnitude
			print(magnitude)
		end

What should I put next? :thinking:

if magnitude <= 10 then
   -- In range, do what you need to here.
end

Wouldn’t that work for only 1 player?

local PlrCount = nil
for i, plr in ipairs(game.Players:GetChildren()) do
PlrCount += 1
			local Character = plr.Character
			local position = Character.HumanoidRootPart.Position - script.Parent.MainOrigin.Position
			local magnitude = position.magnitude
			print(magnitude)
if magnitude <= 10 then -- only for one player, not all, right?
 --put code here
end
		end

Your looping through the players so it will check each player’s magnitude one by one.

--// Services
local Players = game:GetService("Players")

--// For Loop
for _, player in ipairs(Players:GetPlayers()) do
   if player and player:IsDescendantOf(Players) then
       local Character = player.Character
       local Magnitude = (Character.HumanoidRootPart.Position - script.Parent.MainOrigin.Position).magnitude
       if Magnitude <= 10 then
          -- In range!
       end
    end
end

It’s in a loop, so it executes for each player.

Here’s a slightly cleaned up version of your code:

local Players = game:GetService("Players")
local mainOrigin = script.Parent.MainOrigin

local DISTANCE_THRESHOLD = 10

for _, player in ipairs(Players:GetPlayers()) do
	local character = player.Character
	if not character then
		continue
	end

	local distanceFromOrigin = (character.PrimaryPart.Position - mainOrigin.Position).Magnitude
	
	if distanceFromOrigin <= DISTANCE_THRESHOLD then
		--put code here for players that are close to mainOrigin
	end
end
2 Likes

Careful here, one player waiting will cause the entire loop to pause and stop the code from running for all players.

Yeah that’s true I guess it would yield. Also if you return in a loop does it stop the loop or would you instead use continue?

return will exit the function without continuing if it’s inside a function, but will throw an error if it’s not in a function. continue is the right keyword I wanted. Good catch! (Fixed my code snippet now)

Here’s an example of how you can integrate this into a spawning system:

A spawning system using Magnitude checks:
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local DISTANCE_THRESHOLD = 10

local spawns: { BasePart } = Workspace.Spawns:GetChildren()
local cratePrefab: BasePart = ReplicatedStorage.Crate
local crateContainer = Workspace

local function spawnCrate(spawnPart: BasePart)
	local crate = cratePrefab:Clone()
	crate.CFrame = spawnPart.CFrame
	crate.Parent = crateContainer
end

local function getNearbyPlayer(position: Vector3, maxDistance: number)
	for _, player in ipairs(Players:GetPlayers()) do
		local character = player.Character
		if not character then
			continue
		end

		local distanceFromOrigin = (character.PrimaryPart.Position - position).Magnitude
		
		if distanceFromOrigin <= maxDistance then
			return player
		end
	end

	-- No players are within maxDistance of position
	return nil
end

local function getValidSpawn()
	for _, spawnPart in ipairs(spawns) do
		local nearbyPlayer = getNearbyPlayer(spawnPart.Position, DISTANCE_THRESHOLD)

		if not nearbyPlayer then
			return spawnPart
		end
	end

	-- No valid spawn was found, default to a random spawn
	return spawns[math.random(#spawns)]
end

-- Usage:
spawnCrate(getValidSpawn())
Alternatively, you can do it with :GetPartBoundsInRadius():
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local DISTANCE_THRESHOLD = 10

local spawns: { BasePart } = Workspace.Spawns:GetChildren()
local cratePrefab = ReplicatedStorage.Crate
local crateContainer = Workspace

local overlapParams = OverlapParams.new()
overlapParams.FilterType = Enum.RaycastFilterType.Whitelist
overlapParams.MaxParts = 1

local function getHumanoidRootParts()
	local humanoidRootParts = {}

	for _, player in ipairs(Players:GetPlayers()) do
		if player.Character then
			table.insert(humanoidRootParts, player.Character.PrimaryPart)
		end
	end

	return humanoidRootParts
end

local function spawnCrate(spawnPart: BasePart)
	local crate = cratePrefab:Clone()
	crate.CFrame = spawnPart.CFrame
	crate.Parent = crateContainer
end

local function isPlayerNearby(position: Vector3, maxDistance: number)
	overlapParams.FilterDescendantsInstances = getHumanoidRootParts()

	local nearbyPlayerRootParts = Workspace:GetPartBoundsInRadius(position, maxDistance, overlapParams)

	return #nearbyPlayerRootParts ~= 0
end

local function getValidSpawn()
	for _, spawnPart in ipairs(spawns) do
		if not isPlayerNearby(spawnPart.Position, DISTANCE_THRESHOLD) then
			return spawnPart
		end
	end

	-- No valid spawn was found, default to a random spawn
	return spawns[math.random(#spawns)]
end

-- Usage:
spawnCrate(getValidSpawn())

So when testing, It works, (yay) but when 2 player testing, I moved the second player right next to the crate, destroyed it, and it respawned. I think it respawned because the first player was farther than 10 studs, and the second was inside 10 studs. The code checked and made sure that the first player was further than 10 studs, then proceeded with code. :\

Hi :slightly_smiling_face:.

I had a post similar to this… I hope this helps;

Close, I could do that, but then I would have to make a part surrounding the crate, correct, And There will be lots of crates in the game, so the surrounding parts would get annoying when developing, Though I could spawn a part around the MainOrigin…

I reccomend making a folder, and using a loop!

for i,v in pairs() do 
    --do what you what it do here
end 

in this code, the char.PrimaryPart is the part you want to find right? Is there a way to do that but with all parts named HumanoidRootPart?

function getParams(char,parameterpart)
	if table.find(workspace:GetPartsInPart(parameterpart),char.PrimaryPart) then
		print(Char.Name.." found in "..parameterpart.Name)
		return true
	end
end

if getParams(character,part) == true then
    -- does what i want the script to do here
end

I presume something a bit like this…

function getParams(char,parameterpart)
	if table.find(workspace:GetPartsInPart(parameterpart),char.PrimaryPart) then
		print(Char.Name.." found in "..parameterpart.Name)
		return true
	end
end

for _,Player in pairs(game.Players:GetPlayers()) do
    local character = Player.Character
    if getParams(character,part) == true then
        -- does what i want the script to do here
    end
end

I’ve added a solution using :GetPartBoundsInRadius() to my post

Uhh… I guess that works. I just decided to teleport the player back a couple studs… I hope your not mad that I just wasted your time. :grimacing:

for i = 1, 10 do
	print(i)
	if i == 5 then return end
end

A ‘return’ statement doesn’t necessarily have to belong to a function’s body, here’s another example.

do
	print("Printed.")
	if true then return end
	print("Not printed.")
end
1 Like
local Enumeration = Enum
local Game = game
local Workspace = workspace
local Players = Game:GetService("Players")

local Radius = 10 --Change to desired radius.

local function CheckDistanceFromCrate(Crate) --This function expects the 'crate' being spawned as an argument.
	local Parameters = OverlapParams.new()
	Parameters.FilterDescendantsInstances = {Crate}
	Parameters.FilterType = Enumeration.RaycastFilterType.Blacklist
	local Parts = Workspace:GetPartsBoundsInRadius(Crate.Position, Radius, Parameters)
	
	for _, Part in ipairs(Parts) do
		local Model = Part:FindFirstAncestorOfClass("Model")
		if not Model then continue end
		local Humanoid = Model:FindFirstChildOfClass("Humanoid")
		if (not Humanoid) or Humanoid.Health <= 0 then continue end
		local Player = Players:GetPlayerFromCharacter(Model)
		if not Player then continue end
		local Delta = (Model:GetPivot().Position - Crate.Position) --Gets difference of two vectors.
		local Direction = Delta.Unit --Gets direction of crate to player's character.
		local Distance = Delta.Magnitude --Gets distance between crate and player's character.
		Model:PivotTo(Model:GetPivot() + (Direction * (10 - Distance))) --Moves character away from the crate so that they are 10 studs away.
	end
end