NPC Follow Script Isnt Working

Im tryna make a follow script for a mob NPC but has a maximum distance it can go before needing to return to its original spawn point, it was working a few days ago but today it broke and now the mob just walks back and forth in the same place. I cant seem to figure out why and ive spent about two hours tryna figure it out

StartPosition = script.Parent.HumanoidRootPart.Position
Anim = script:WaitForChild("RunAnim")
Anim2 = script:WaitForChild("IdleAnim")
Current = script.Parent.MobHumanoid:LoadAnimation(Anim)
Current2 = script.Parent.MobHumanoid:LoadAnimation(Anim2)
Current2:Play()
Animate = false
while true do
local FindDistance = 100
local MaxDistance = 200
local MobHumanoid = script.Parent:WaitForChild("MobHumanoid")
local Root2 = script.Parent:WaitForChild("HumanoidRootPart")
local dist = nil
local Root = nil
local Humanoid = nil
local Player = nil
local FindPlayers = game.Workspace:GetChildren()
for i = 1, #FindPlayers do
Player = FindPlayers[i]
if Player:isA("Model") then
Root = Player:findFirstChild("HumanoidRootPart")
Humanoid = Player:findFirstChild("Humanoid")
if (Root ~= nil) and (Humanoid ~= nil) and (Humanoid.Health > 0) then
dist = (Root2.Position - Root.Position).magnitude
fardist = (Root2.Position - StartPosition).magnitude
if dist < FindDistance and fardist < MaxDistance then
--script.Parent.HumanoidRootPart.Anchored = false
script.Parent.MobHumanoid:MoveTo(Root.Position)
if Animate == false then
Current:Play()
Animate = true
end
else
restdist = (Root2.Position - StartPosition).magnitude
Current:Stop()
Animate = false
--script.Parent.HumanoidRootPart.Anchored = true
if restdist >= 15 then
--script.Parent.HumanoidRootPart.Anchored = false
if Animate == false then
Current:Play()
Animate = true
end
script.Parent.MobHumanoid:MoveTo(StartPosition)
repeat
restdist = (Root2.Position - StartPosition).magnitude
wait()
until restdist < 15
end
end
end
end
end
wait()
end

I can’t edit your code right now since I’m on mobile but I can tell you what you could possibly do to fix it

  1. RunService - You could use RunService.Heartbeat instead of a loop to check the magnitude of the NPC and player then if it exceeds the maximum stud distance, use Humanoid:MoveTo() to make the NPC walk back

I typically use events for this, an event to trigger the RunService thread and disconnecting it when the NPC returns to prevent it from walking back and forth

  1. Event disconnecting - When the script detects that the NPC extends the maximum stud distance, it should disconnect all events that make the NPC move away from it to prevent it from moving back and forth

You would have to reconnect all the events afterwards though

I also noticed that you use a few deprecated things such as isA and findFirstChild instead of IsA and FindFirstChild

When I get back on my computer (which will be hours from now) I’ll give a few code examples

Okay, definitely let me know how to do the event disconnect,. Tryna cut down lag as much as possible and loops are good for lag

RunService = game:GetService("RunService")
local StartPosition = script.Parent.HumanoidRootPart.Position
local FindDistance = 30
local MaxDistance = 30
local MobHumanoid = script.Parent:WaitForChild("MobHumanoid")
local HumanoidRootPart = script.Parent:WaitForChild("HumanoidRootPart")
local SpecificObject = nil
local PlayerHumanoid = nil
local PlayerHumanoidRootPart = nil
local Following = false
local Distance = nil
local StartPositionDistance= nil
local RestingDistance = nil
local Resting = false
local FollowedPlayer = nil
local FollowedPlayerHumanoidRootPart = nil
local FollowedPlayerHumanoid = nil
local Distance2 = nil
function Follow(Root)
if Resting == false then
Following = true
script.Parent.MobHumanoid:MoveTo(Root.Position)
end
end
function Return(Root)
if Following == true then
Following = false
Resting = true
FollowedPlayer = nil
script.Parent.MobHumanoid:MoveTo(StartPosition)
end
end
function Check()
local WorkspaceObjects = game.Workspace:GetChildren()
for i = 1, #WorkspaceObjects do
SpecificObject = WorkspaceObjects[i]
if SpecificObject:FindFirstChild("Humanoid") ~= nil then
PlayerHumanoid = SpecificObject:findFirstChild("Humanoid")
PlayerHumanoidRootPart = SpecificObject:findFirstChild("HumanoidRootPart")
if (PlayerHumanoid ~= nil) and (PlayerHumanoidRootPart ~= nil) and (PlayerHumanoid.Health > 0) then
Distance = (HumanoidRootPart.Position - PlayerHumanoidRootPart.Position).magnitude
StartPositionDistance = (HumanoidRootPart.Position - StartPosition).magnitude
if Distance < FindDistance and StartPositionDistance < MaxDistance then
FollowedPlayer = SpecificObject
FollowedPlayerHumanoidRootPart = FollowedPlayer:findFirstChild("HumanoidRootPart")
FollowedPlayerHumanoid = FollowedPlayer:findFirstChild("Humanoid")
print("Trying To Follow")
Follow(FollowedPlayerHumanoidRootPart)
elseif FollowedPlayer ~= nil then
Distance2 = (HumanoidRootPart.Position - FollowedPlayerHumanoidRootPart.Position).magnitude
if Distance2 > FindDistance or StartPositionDistance > MaxDistance or (FollowedPlayerHumanoid.Health <= 0) or Resting == true then
print("Return")
if StartPositionDistance < 3 then
Resting = false
end
Return(HumanoidRootPart)
end
end
end
end
end
end
RunService.Heartbeat:Connect(Check)

I got it fixed and working now, is there any way I might could clean the code up more, any suggestions?

I suggest indentions and spaces because everything looks jumbled together

Ive never used typical coding format, I cant read it for some reason when its that way

Well, if it’s for personal preference then it’s fine, but if you release something like a public module I suggest doing that

Other than that, I don’t really have anything else

Also, an example of event disconnection would be:

local bindable = Instance.new("BindableEvent")

local connection -- this is called an upvalue, it's essentially making the variable "nil" without typing "nil"

connection = bindable.Event:Connect(function(connect)
    if not connect then 
       connection:Disconnect() -- this would disconnect the event so that any further fires wouldn't call this thread
    else
       print("connection still established")
    end
end)

bindable:Fire(true)
bindable:Fire(false)