How to detect only one nearest humanoid

I have some issue with detecting humanoid, this script can detect nearby humanoid but it will also detect any humanoids within radius which is what i don’t want

What i want to achieve was making it detect only the nearest humanoid, if any closer humanoid, it will change its target to that humanoid

--this is a server script, this script use by a loop
    local function FindNearbyHumanoid(position,center)
		for i, humanoids in pairs(game.Workspace:GetDescendants()) do
			if humanoids and humanoids:IsA("Humanoid") and humanoids ~= character:FindFirstChild("Humanoid") and humanoids.Health > 0 then
				local target = humanoids:FindFirstAncestorOfClass("Model")
				if target and target ~= character then
					if target.PrimaryPart or target:FindFirstChild("Humanoid") then
						local distance = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position)
						if newtargetdistance == nil or distance.magnitude < maxrange then
							closest = target
							print(closest.Name.." Is Nearby")
							direction = distance.Unit
							newtargetdistance = distance.magnitude
						end
					end
				end
			end
		end
		return closest, newtargetdistance
	end

appreciate any help

2 Likes

It looks like you are trying to find the nearest humanoid to the character in the script. To do this, you can add a check to see if the distance between the character and the current humanoid is less than the distance to the closest humanoid found so far.

Here is how you can modify the code to achieve this:

local function FindNearbyHumanoid(position,center)
    local closest = nil
    local newtargetdistance = nil
    for i, humanoids in pairs(game.Workspace:GetDescendants()) do
        if humanoids and humanoids:IsA("Humanoid") and humanoids ~= character:FindFirstChild("Humanoid") and humanoids.Health > 0 then
            local target = humanoids:FindFirstAncestorOfClass("Model")
            if target and target ~= character then
                if target.PrimaryPart or target:FindFirstChild("Humanoid") then
                    local distance = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position).magnitude
                    if newtargetdistance == nil or distance < newtargetdistance then
                        closest = target
                        print(closest.Name.." Is Nearby")
                        direction = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position).Unit
                        newtargetdistance = distance
                    end
                end
            end
        end
    end
    return closest, newtargetdistance
end

This code will find the nearest humanoid to the character and update the closest variable with the nearest humanoid found so far.

I generated this response with https://chat.openai.com/chat, let me know if you have any further questions and I’ll give the AI that. Note that sometimes the code it generates is wrong and some manual fixing has to be done. I haven’t tested this now but from my eye it looks correct.

It’s the same, the radius decreases as long as i approach humanoid, this probably because

return closest, newtargetdistance

didn’t work but i don’t know what to replace with this line

I can’t really visualise what the problem would be, could you provide some more information? The return statement should work and that is probably not what is causing the issue.

NewTargetDistance is set as the detected distance to humanoid example here is the distance from player from target is 20 studs
image
:green_circle: is max radius range that the dection can find | :red_circle: is the distance between player and target
So in the script

                    if newtargetdistance == nil or distance < newtargetdistance then
                        closest = target
                        print(closest.Name.." Is Nearby")
                        direction = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position).Unit
                        newtargetdistance = distance
                    end

So NewTargetDistance being used to compare between distances found by the detection so the range of detecting decreases as the player move away
image
:green_circle: is max radius range that the dection can find | :red_circle: is the distance between player and target

It looks like the issue is that newtargetdistance is being updated every time a new humanoid is found, even if it is not the nearest. To fix this, you can update newtargetdistance only when a new nearest humanoid is found.

Here is how you can modify the code to achieve this:

local function FindNearbyHumanoid(position,center)
    local closest = nil
    local newtargetdistance = nil
    for i, humanoids in pairs(game.Workspace:GetDescendants()) do
        if humanoids and humanoids:IsA("Humanoid") and humanoids ~= character:FindFirstChild("Humanoid") and humanoids.Health > 0 then
            local target = humanoids:FindFirstAncestorOfClass("Model")
            if target and target ~= character then
                if target.PrimaryPart or target:FindFirstChild("Humanoid") then
                    local distance = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position).magnitude
                    if newtargetdistance == nil or (distance < newtargetdistance and distance < maxrange) then
                        closest = target
                        print(closest.Name.." Is Nearby")
                        direction = (humanoidrootpart.Position - target:FindFirstChild("HumanoidRootPart").Position).Unit
                        newtargetdistance = distance
                    end
                end
            end
        end
    end
    return closest, newtargetdistance
end

This code will find the nearest humanoid to the character within the maximum range and update the closest variable with the nearest humanoid found so far. It will also update the newtargetdistance variable only when a new nearest humanoid is found.

I hope this helps! Let me know if you have any questions.

Other than that it’s not really clear to me what the issue is. One possibility could be that there are multiple nested conditional statements, and it may be necessary to try different approaches until a solution is found.

Same issue appears, multiple humanoids detected

(ignore this)

Hello there. So, I created a little demo that does something similar to what you want. Here’s the code for that:

-- Services --

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Variables --

local Player = Players.LocalPlayer
local Character = Player.Character or Player.Character:Wait()
local HumanoidRootPart = Character.HumanoidRootPart

local Humanoids = workspace.Humanoids
local RadMax = workspace.RadMax
local RadMin = workspace.RadMin
local Highlight = ReplicatedStorage.Highlight

local MaxRadius = 30

-- Functions --

local function FindNearest()
	local Closest -- Setting to nil since there is no reason to be set to anything.
	local ClosestDistance = math.huge -- Setting it to math.huge in order to compare it.
	
	for _, TargetCharacter in ipairs(Humanoids:GetChildren()) do -- Looping through all children of the "Humanoids" folder. In your case, this could be different, along with all the checks.
		local TargetHumanoid = TargetCharacter:FindFirstChild("Humanoid") -- Gets the Humanoid of the model.
		local TargetHumanoidRootPart = TargetCharacter:FindFirstChild("HumanoidRootPart") -- Gets the HumanoidRootPart of the model.
		if TargetCharacter:IsA("Model") and TargetHumanoid and TargetHumanoidRootPart and TargetHumanoid.Health > 0 then -- Checking if the "TargetCharacter" is a model, has a Humanoid, has a HumanoidRootPart, and if the humanoid's healt his bigger than 0. This check could be specialized for your case.
			local Distance = (HumanoidRootPart.Position - TargetHumanoidRootPart.Position).magnitude -- Gets the distance between the character's HumanoidRootPart and the target's HumanoidRootPart.
			if Distance <= MaxRadius and Distance < ClosestDistance then -- Checking if the character is within our max radius and if the distance is smaller than the closest distance so far.
				Closest = TargetCharacter -- Setting the closest character to the current one.
				ClosestDistance = Distance -- Setting the closest character distance to the current one.
			end
		end
	end
	
	if not Closest then ClosestDistance = nil end -- Set the ClosestDistance to nil if there is no close player.
	return Closest, ClosestDistance -- Return Closest and ClosestDistance.
end

-- Scripting --

RadMax.Size = Vector3.new(0.2, MaxRadius * 2, MaxRadius * 2)

while task.wait(0.1) do
	RadMax.Position = Vector3.new(HumanoidRootPart.Position.X, 0.1, HumanoidRootPart.Position.Z)
	
	local Closest, ClosestDistance = FindNearest()
	if Closest then
		Highlight.Parent = Closest
		RadMin.Position = Vector3.new(HumanoidRootPart.Position.X, 0.15, HumanoidRootPart.Position.Z)
		RadMin.Size = Vector3.new(0.3, ClosestDistance * 2, ClosestDistance * 2)
		RadMin.Parent = workspace
		RadMax.Color = Color3.fromRGB(170, 170, 0)
	else
		Highlight.Parent = ReplicatedStorage
		RadMin.Parent = ReplicatedStorage
		RadMax.Color = Color3.fromRGB(31, 128, 29)
	end
end

And here’s a little clip of how it works:

As you can see, it will always “lock” onto the closest character that meets the requirement, which are that it is a character, that its health is greater than zero, and that it is a 30-stud radius of the player.

Now, this is meant to be used as a concept. I put comments on each line of the FindNearest() function that explain what is happening. You should modify it to work for your case, but nonetheless, that is how it’s going to work;

  1. Check if it is a character and has both a Humanoid and HumanoidRootPart
  2. Check if its health is greater than 0
  3. Check if it is within your max radius
  4. Check if the distance is smaller than the currently smallest distance
    4.1 If it is, set it to be the closest and the smallest distance
  5. Return the closest and smallest distance, if any

Hopefully this helped you. If you have any questions, do let me know.

5 Likes

I just realized that my script quite works the same, i used print() to print founded character, resulting multiple humanoids were detected, so i used your method HighLight them, thanks for your improvement

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