Trying to check if an npc is within proximity

i have a script i got from the devforum which detects if a player is close to another player. problem is, is that its detecting npcs. how can i tell the script to ignore npcs?

script:

local myHrp = script.Parent:WaitForChild("HumanoidRootPart")
local radius = 25
local enabled = false

while true and wait() do
	enabled = false
	
	local plrs = workspace:GetChildren()
	for i = 1, #plrs do
		if plrs[i].Name ~= script.Parent.Name then -- if child name is not MY character's name then. (exclude) MY character
			local hum:Humanoid = plrs[i]:FindFirstChild("Humanoid")
			local PlrHRP = plrs[i]:FindFirstChild("HumanoidRootPart")
			
			if myHrp and PlrHRP and hum.Health > 0 then -- trying to check if an npc is in proximity. if it is, then i want the npc to be ignored. <-
				local distance = (myHrp.Position - PlrHRP.Position).Magnitude
				if distance < radius then
					print("player is CLOSE!")
					wait(5)
					enabled = true
				end
			end
		end
	end
end
2 Likes

In this update of the script you’ve used, NPCs are implicitly ignored because they won’t be included in the list obtained by game.Players:GetPlayers().

local myHrp = script.Parent:WaitForChild("HumanoidRootPart")
local radius = 25
local enabled = false

while true do
    enabled = false

    local plrs = game.Players:GetPlayers() -- Get a list of all players in the game
    for i = 1, #plrs do
        local character = plrs[i].Character
        if character and character ~= script.Parent then
            local hum = character:FindFirstChildOfClass("Humanoid")
            local PlrHRP = character:FindFirstChild("HumanoidRootPart")

            if hum and PlrHRP and hum.Health > 0 then
                local distance = (myHrp.Position - PlrHRP.Position).Magnitude
                if distance < radius then
                    print("Player is CLOSE!")
                    wait(5)
                    enabled = true
                end
            end
        end
    end

    wait()
end
1 Like

by “ignore npc” you mean just target players?..

well try to use

game:getservice("players":):getplayerfromcharacter(`` Model here ``)

--Example
local a = workspace.NPC
local isPlayer game:getservice("players":):getplayerfromcharacter(a)

if isplayer then

local achar = isplayer.Character <-- this is i think what you are looking for

print("is a player")
else
print("nope not a player")
end
1 Like

I know other people already gave some solutions but you could also do.

 if hum and hum:IsA("Player") and PlrHRP and hum.Health > 0 then
1 Like

@markjac @hesoyam2k14 @PipeSader

hey guys, tysm for the replies i really appreciate it. unfortunately i tried all of your scripts that you sent and even modified them to a degree but its not working. sorry if i gave a wacky explanation, im trying to make the script check if a plr is close to another plr and i want to SKIP npcs, etc.

i tried this but theres still nothing unfortunately.

local char = script.Parent
local myHRP = char:WaitForChild("HumanoidRootPart")
local radius = 15
local enabled = false

while true and wait() do
	enabled = false


	local plrs = workspace:GetChildren()
	for i = 1, #plrs do
		if plrs[i].Name ~= script.Parent.Name then
			if not plrs[i]:IsA("Player") then continue end
		local PlrHRP = plrs[i]:FindFirstChild("HumanoidRootPart")



		if myHRP and PlrHRP then
				local dist = (myHRP.Position-PlrHRP.Position).Magnitude
			if dist <= radius then
				print("player is close!")
				wait(3)
				enabled = true
				end
			end
		end	
	end
end
1 Like

To skip NPCs and entities without a HumanoidRootPart you can add additional conditions inside the loop like this:

local char = script.Parent
local myHRP = char:WaitForChild("HumanoidRootPart")
local radius = 15
local enabled = false

while true do
	enabled = false

	local plrs = game.Players:GetPlayers()
	for i, plr in ipairs(plrs) do
		if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") and plr.Name ~= char.Name then
			local PlrHRP = plr.Character.HumanoidRootPart
			local dist = (myHRP.Position - PlrHRP.Position).Magnitude

			if dist <= radius then
				print("Player", plr.Name, "is close!")
				wait(3)
				enabled = true
			end
		end
	end

	wait() -- Wait for a short time before checking again
end
1 Like

i tried the script and it doesnt work so i tried other things and yup. i still got nothin’. :frowning_face:

i was trying to do like; in the for loop if the child’s name wasn’t a players name then continue end (skip it)

like this but it doesnt work:

local char = script.Parent
local myHRP = char:WaitForChild("HumanoidRootPart")
local radius = 15
local enabled = false

while true do
	enabled = false

	local plrs = game.Players:GetPlayers()
	for i, plr in ipairs(plrs) do
		if char and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") and plr.Name ~= char.Name then
			for index, model in pairs(workspace:GetChildren()) do
				if model.Name ~= plr.Name then continue end
			end
			
			local PlrHRP = plr.Character.HumanoidRootPart
			local dist = (myHRP.Position - PlrHRP.Position).Magnitude

			if dist <= radius then
				print("Player", plr.Name, "is close!")
				wait(3)
				enabled = true
			end
		end
	end

	wait() -- Wait for a short time before checking again
end
1 Like

In this modification i replaced the “continue” statement with “break” to exit the loop if the player’s name is found in the workspace. Therefore, if the player’s name is encountered while iterating through the workspace’s children, the loop will immediately terminate, skipping the remainder of the code within the loop body for that iteration, Let me know if it works the way you need:

script:

local char = script.Parent
local myHRP = char:WaitForChild("HumanoidRootPart")
local radius = 15
local enabled = false

while true do
	enabled = false

	local plrs = game.Players:GetPlayers()
	for i, plr in ipairs(plrs) do
		if char and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") and plr.Name ~= char.Name then
			local playerFound = false -- Flag to check if player is found in the workspace
			
			-- Check if the player's name exists as a child in the workspace
			for index, model in pairs(workspace:GetChildren()) do
				if model.Name == plr.Name then
					playerFound = true
					break -- Exit the loop early if player is found
				end
			end
			
			if not playerFound then
				local PlrHRP = plr.Character.HumanoidRootPart
				local dist = (myHRP.Position - PlrHRP.Position).Magnitude

				if dist <= radius then
					print("Player", plr.Name, "is close!")
					wait(3)
					enabled = true
				end
			end
		end
	end

	wait() -- Wait for a short time before checking again
end

Hi! I was wondering if you could try perhaps getting the current Players in the server, then running an if statement for if a player touches the proximity part (assuming it is an invisible part – like a hitbox). I believe using this would get rid of any other “noises” and also might be better than using a while loop?

local Players = game:GetService("Players")

local Player = nil
local Playerings = {}
task.wait(5)
--To update player tables you can use a PlayerAdded event

print(Players)
for _, player in pairs(Players:GetPlayers()) do
	Player = player -- set the name from nil to player
	table.insert(Playerings, Player) -- Insert player name into table
	print(Player) -- debug output
end

local function PlayerProximity()
	print("This is a player!") -- Checks out
	--Customize the function to however you like
end

local object = script.Parent

object.Touched:Connect(function(other) -- Connect a function to the event
	local model = other.Parent
	print(tostring(model))
	local match = false -- Initialize a boolean variable to store the match result
	for _, PlayerOBJ in ipairs(Playerings) do -- Loop over the keys of the Playerings table (indexed table)
		print(PlayerOBJ)
		if tostring(PlayerOBJ) == tostring(model) then -- Compare the key (as a string) to model (as a string)
			match = true -- Set the match variable to true
			break
		else
			print("Not a player!")
		end
	end
	if match then 
		PlayerProximity() -- Call the function
	end
end)
1 Like

hello calculus!

that’s a great idea and im 100% going to be using that in the future however, i just want the players and not the npcs/rigs. at the moment the script prints if the player is close to a rig/npc and i dont want that. :slight_smile:


local myHrp = script.Parent:WaitForChild("HumanoidRootPart")
local radius = 25
local enabled = false

while true and wait() do
	enabled = false
	
	local plrs = workspace:GetChildren()
	for i = 1, #plrs do
		if plrs[i].Name ~= script.Parent.Name then -- if child name is not MY character's name then. (exclude) MY character
			local hum:Humanoid = plrs[i]:FindFirstChild("Humanoid")
			local PlrHRP = plrs[i]:FindFirstChild("HumanoidRootPart")
			
			if myHrp and PlrHRP and hum.Health > 0 then -- trying to check if an npc is in proximity. if it is, then i want the npc to be ignored. <-
				local distance = (myHrp.Position - PlrHRP.Position).Magnitude
				if distance < radius then
					print("player is CLOSE!")
					wait(5)
					enabled = true
				end
			end
		end
	end
end
1 Like

Ok just for clarification, you want it so if the Player touches the NPC the script activates, or do you want it so that if a player is in the NPC range the script activates? Depending on how you want it, the script I provided will only work if you touch the invisible part, which would be around your NPC/part.

For example, in the following image:

image

The touched event is connected to the “hitbox” or the sphere, we can make the sphere transparency 1 to have it so that the player can’t see it but can still activate it. This would represent the range. If you don’t want it as near, you can decrease the size of the hitbox to however you would like. So if you want it so the player has to make contact with the object, you can place the script as a child of the object, rather than a hitbox style. I hope this helps!

1 Like

basically i want it so that if the player is in range with another player the script activates. but if the player is in range with an NPC, then i want it to ignore the npc. i only want it so that it will only detect player range and not player/npc range. sorry if this makes no sense!

1 Like

Oh that makes sense! In order to do that, all you would need to do is modify your plrs table to only get Player models, which you can do by checking if the name of the object is in the Players table.

local myHrp = script.Parent:WaitForChild("HumanoidRootPart")
local radius = 25
local enabled = false
local Players = game:GetService("Players")

local Playerings = {}

for _, player in ipairs(Players:GetPlayers()) do
	table.insert(Playerings, player)
end

while true and wait() do
	enabled = false

	local plrs = workspace:GetChildren()

	print(Playerings)
	for i = 1, #plrs do
		if plrs[i].Name ~= script.Parent.Name then -- if child name is not MY character's name then. (exclude) MY character
			for _, playerName in ipairs(Playerings) do
				if tostring(playerName) == tostring(plrs[i].Name) then
					local hum:Humanoid = plrs[i]:FindFirstChild("Humanoid")
					local PlrHRP = plrs[i]:FindFirstChild("HumanoidRootPart")

					if myHrp and PlrHRP and hum.Health > 0 then -- trying to check if an npc is in proximity. if it is, then i want the npc to be ignored. <-
						local distance = (myHrp.Position - PlrHRP.Position).Magnitude
						if distance < radius then
							print("player is CLOSE!")
							print(playerName, plrs[i].Name)
							wait(5)
							enabled = true
						end
					end
				else
					print("Not a player!")
					wait(1)
				end
			end
		end
	end
end

I hope this works to your liking! (Additionally, you can remove the else statement if the wait is too long)

1 Like

perfect job man, it works. i modified it a bit and it works better like this but u got it! tysm for spending the time to help me! :slight_smile:

one question ab print statements tho! is there any way to prevent the print statements from like excessively printing. the else statement prints like every milisecond basically.

finished script:

local myHrp = script.Parent:WaitForChild("HumanoidRootPart")
local radius = 25
local enabled = false
local Players = game:GetService("Players")

local Playerings = {}

for _, player in ipairs(Players:GetPlayers()) do
	table.insert(Playerings, player)
end

while true and wait() do
	enabled = false

	local plrs = workspace:GetChildren()

	print(Playerings)
	for i = 1, #plrs do
		if plrs[i].Name ~= script.Parent.Name then -- if child name is not MY character's name then. (exclude) MY character
			for _, playerName in ipairs(Playerings) do
				if tostring(playerName) == tostring(plrs[i].Name) then
					local hum:Humanoid = plrs[i]:FindFirstChild("Humanoid")
					local PlrHRP = plrs[i]:FindFirstChild("HumanoidRootPart")

					if myHrp and PlrHRP and hum.Health > 0 then -- trying to check if an npc is in proximity. if it is, then i want the npc to be ignored. <-
						local distance = (myHrp.Position - PlrHRP.Position).Magnitude
						if distance < radius then
							print("player is CLOSE!")
							print(playerName, plrs[i].Name)
							wait(5)
							enabled = true
						else
							print("not player")
						end
					end
				end
			end
		end
	end
end
1 Like

Oh yea, you can remove the else statement if you would like since there is no functionality if it was not a player, the print statement was only needed to debug, or if for some reason it was not functioning as intended. I’m glad it was working as expected!

1 Like

yes ofc. tysm once again! that was really helpful. :smiley:

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