Enemy NPC not moving after first attack

When the NPC moves toward a player and attacks and the player dies or moves away it just stays there.

while wait() do
	local target = FindTarget()
	
	if target then
		if CanAttack(target)==true then
			hum:MoveTo(script.Parent.Position)
			Attack(target)
		else
			hum.MoveToFinished:Wait()
			hum:MoveTo(target.HumanoidRootPart.Position,target.HumanoidRootPart)
		end
	end
end
5 Likes

Can you show me the CanAttack, Attack, FindTarget functions and the parent of the script?

3 Likes
function FindTarget()
	local bestTarget = nil
	local range = config:WaitForChild("PatrolRange")

	for i, enemy in ipairs(workspace:GetChildren()) do
		if Players:GetPlayerFromCharacter(enemy) then
			local distanceToEnemy = (enemy.HumanoidRootPart.Position-npc.HumanoidRootPart.Position).Magnitude

			if distanceToEnemy <= range.Value then
				range.Value = distanceToEnemy
				bestTarget = enemy
			end
		end
	end	

	return bestTarget
end

local function CanAttack(target)
	if (target.PrimaryPart.Position-script.Parent.Position).Magnitude <= config.AttackRange.Value then
		return true
	else
		return false
	end
end

local function Attack(target)


		local Animation = hum.Animator:LoadAnimation(anims.Attack)

		Animation:Play()
		Animation.Stopped:Wait()
		
		target.Humanoid:TakeDamage(config.Damage.Value)		
	
	
	task.wait(config.Cooldown.Value)
end

The parent is the NPC’s root part.

2 Likes

Aren’t NPC supposed to stay when player dies or player moves away from the range? Can you tell me the issue more specifically?

2 Likes

No? The while loop is there and it finds the nearest target (which is the same person) and checks if it can attack, otherwise it moves. It keeps while looping to check that to. I’m not sure if the issue can be explained more specifically, it’s just when it attacks, when the player moves away or is now dead it stays there.

1 Like

How does the NPC start moving? In this case it appears the NPC won’t start moving unless you started them before the while loop or you happen to be in range at the start.

hum.movetofinished:Wait()

After attack runs though, there is no MoveTo() so the wait never ends when it goes to the other side of the if statement.

1 Like
while wait() do
	local target = FindTarget()
	
	if target then
		hum:MoveTo(script.Parent.Position)
		if CanAttack(target)==true then
			hum:MoveTo(script.Parent.Position)
			Attack(target)
		else
			hum.MoveToFinished:Wait()
			hum:MoveTo(target.HumanoidRootPart.Position,target.HumanoidRootPart)
		end
	end
end

added a moveto(), still dosen’t work. Forgot to mention, if you get in it’s attack range again, it will attack you and move just a little.

1 Like

If you temporarily remove that hum.MoveToFinished:Wait(), does it work? And looking at your code, you may want to be doing a task.spawn(Attack, target) instead of Attack(target) though I might misunderstand the intended functionality.

1 Like
while wait() do
	local target = FindTarget()
	
	if target then
	--	hum:MoveTo(script.Parent.Position)
		if CanAttack(target)==true then
			hum:MoveTo(script.Parent.Position)
			Attack(target)
		else
		--	hum.MoveToFinished:Wait()
			hum:MoveTo(target.HumanoidRootPart.Position,target.HumanoidRootPart)
		end
	end
end

I tried doing that, but it failed.

1 Like

Ahh. I copied your code and made a couple adjustments to get it to work on my end and narrowed it down to your FindTarget() function. After the first attack, it’s actually getting nil as a target. This is because you are overwriting the number value there. Try this function instead

function FindTarget()
	local bestTarget = nil
	local range = config:WaitForChild("PatrolRange")
	local dist = range.Value

	for i, enemy in ipairs(workspace:GetChildren()) do
		if game.Players:GetPlayerFromCharacter(enemy) then
			local distanceToEnemy = (enemy.HumanoidRootPart.Position-npc.HumanoidRootPart.Position).Magnitude

			if distanceToEnemy <= dist then
				dist = distanceToEnemy
				bestTarget = enemy
			end
		end
	end	

	return bestTarget
end

Basically your code was changing the range to be the smallest range that it ever found a player at, so at some point, the npc couldn’t see the player because its range shrunk too much.

One extra thing I should note though. You are searching the children of workspace for your target. It might make more sense to search through game.Players:GetChildren() and do player.Character as the target. That way you’re not going through all the parts and stuff that aren’t players in workspace every time. Just note you will have to check that the player actually exists if you go that route since character is sometimes nil.

Thanks, I understand what you changed, and it works!

1 Like

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