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
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
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.
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.
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.
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.
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
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.