How do you make an npc follow the closest player if it's been attacked?

I’ve watched a YT tutorial on how to make an npc follow the player, but I’m trying to modify it so that it only follows the player if it gets attacked by a player. So far I have done this, a script in the HumanoidRootPart of the NPC.

local Beam = game.Workspace.Beam
local npcHRP = script.Parent

local function GetNearestPlayer(minimumDistance)
    local closestMagnitude = minimumDistance or math.huge
    local closestPlayer
    for i,v in next, game.Players:GetPlayers() do
        local Character = v.Character
        if (Character) then
            local humanoid = Character.Humanoid
            local HRP = Character.HumanoidRootPart
            if (humanoid.Health > 0) then
                local mag = (npcHRP.Position - HRP.Position).Magnitude
                if (mag <= closestMagnitude) then
                    closestPlayer = v
                    closestMagnitude = mag
                end
            end
        end
    end
    return closestPlayer
end
function ontouchedBeam(hit)
    if hit == "Beam" then
        GetNearestPlayer()
    end
end
script.Parent.Touched:Connect(ontouchedBeam)

I’m not getting any errors, and I know it has something to do with

GetNearestPlayer()

But I just don’t understand it.

2 Likes

The problem isn’t with your GetNearestPlayer() function. It’s a standard iteration to find the closest player, although for i, v in pairs() is more commonly used than for i,v in next,

The hit variable in .Touched functions will always be a BasePart. The if hit == "Beam" then condition will never be satisfied because hit is not a string. print(hit) may display the string name of hit, but hit is still a part nonetheless.

I’m assuming you’re checking the name of hit against the string “Beam”, so you would use `if hit.Name == “Beam”.

1 Like
local Beam = game.Workspace.Beam
local npcHRP = script.Parent

local function GetNearestPlayer(minimumDistance)
    local closestMagnitude = minimumDistance or math.huge
    local closestPlayer
    for i,v in next, game.Players:GetPlayers() do
		local Character = v.Character
		if (Character) then
			local humanoid = Character.Humanoid
			local HRP = Character.HumanoidRootPart
			if (humanoid.Health > 0) then
				local mag = (npcHRP.Position - HRP.Position).Magnitude
				if (mag <= closestMagnitude) then
					closestPlayer = v
					closestMagnitude = mag
				end
			end
		end
	end
	return closestPlayer
end
function ontouchedBeam(hit)
	if hit.Name == "Beam" then
		GetNearestPlayer()
	end
end
script.Parent.Touched:Connect(ontouchedBeam)

I have changed it to that yet nothing happens

Could you further explain what it means for the player to “get attacked”?

Also, please use basic debugging strategies to further understand your problem before posting it to the devforum. Does the condition inside of ontouchedBeam ever become satisfied? You should always use print statements if you don’t know if sections of the code are running or not.

What exactly are you looking for with hit == "Beam"? Are you looking for a part named beam? A Beam instance (which won’t activate Touched events)?

GetNearestPlayer() in itself doesn’t do anything other than return a value. If you want the npc to actually move to that position, you will need to do Humanoid:MoveTo().

1 Like

Wait, so if the beam instance wont activate touched events then how is this working?

  Beam.Touched:Connect(function(hit)
			if hit.Parent:FindFirstChild("Enemy") then
				print('Humanoid is taking damage!')	
				local humanoid = hit.Parent:FindFirstChild('Enemy')	
            	     humanoid.Health = humanoid.Health - damage
            	 	Beam:Destroy()
			end
			end)

(Part of the script used for creating the beams)

Touched events don’t work on Beam instances, so clearly this isn’t a beam. Maybe you’re using a part to serve as a beam?

image

1 Like

Yeah, I am using a part and just naming it Beam

In case you didn’t find solution or someone else comes across this that might need. The following works:

local Humanoid = script.Parent.Humanoid
function findNearestTorso(pos)
	local list = game.Workspace:children()
	local torso = nil
	local dist = 100
	local temp = nil
	local human = nil
	local temp2 = nil
	for x = 1, #list do
		temp2 = list[x]
		if (temp2.className == "Model") and (temp2 ~= script.Parent) and temp2:FindFirstChild("Reward") == nil then
			temp = temp2:findFirstChild("HumanoidRootPart")
			human = temp2:findFirstChild("Humanoid")
			if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
				if (temp.Position - pos).magnitude < dist then
					torso = temp
					dist = (temp.Position - pos).magnitude
				end
			end
		end
	end
	return torso
end

Humanoid:GetPropertyChangedSignal("Health"):Connect(function()
	local healthChange = Humanoid.Health/Humanoid.MaxHealth
	if Humanoid.Health >= 0 and Humanoid.Health <= Humanoid.MaxHealth then
while wait(2) do
	local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
				script.Parent.Humanoid:MoveTo(target.Position, target)
	end
end	
	end
end)

This will make npc follow nearest player only if npc health has changed.

1 Like