My enemy that follows you is kinda twitchy

So basically I made an npc where if you get in it’s hitbox it will start chasing you, however it’s really twitchy and stuff and I’m wondering how I can fix this, here’s footage of it:


Here’s my code:

local hitbox = script.Parent:FindFirstChild("HITBOX")
local pathFindingService = game:GetService("PathfindingService")
local npcHumanoid = script.Parent:FindFirstChild("Humanoid")
local npcTorso = script.Parent:FindFirstChild("Torso")
while true do 
	wait()
	local partsInRegion = workspace:GetPartBoundsInBox(hitbox.CFrame, hitbox.Size, nil)
	for i, object in pairs(partsInRegion) do
		if object.Parent:FindFirstChild("Humanoid") then
			local route = pathFindingService:CreatePath()
			route:ComputeAsync(npcTorso.Position, object.Position)
			local waypoints = route:GetWaypoints()
			for i, waypoint in pairs(waypoints) do
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					npcHumanoid:ChangeState("Jumping")
				end
				npcHumanoid:MoveTo(waypoint.Position)
				npcHumanoid.MoveToFinished:Wait(3)
			end
			npcHumanoid:MoveTo(object.Position)
		end
	end
end

There’s also a bug where he will chase you beyond the 3 seconds, anyone know how to fix?
Also, my explorer looks like this:

maybe instead of a while loop, you could use a .Heartbeat event?
it shouldn’t affect much

try passing on some agent parameters inside the :CreatePath() function

pathfinding is tedious and you should probably hate it

oh yeah and try doing if path.Status == Enum.PathStatus.Success and then running the while loop with everything in it

try setting the NetworkOwner of the NPC primary part to nil at the top of the script

script.Parent.PrimaryPart:SetNetworkOwner(nil)

Maybe instead of doing that try using ray casts on all the players characters and then get their Distances. If a player is in range you’ll chase em

1 Like

Just a suggestion, but why not use Shapecasts to detect a player in the radius (not a square) from the player?

It probably doesn’t need to be done every frame either. Every .1 or .2 seconds may be close enough to do your checks.

1 Like

would I do this before the 2nd for i, v loop? the one with for i, waypoint in waypoints? or would i state this before or afterhand

Never use .Heartbeat as it constantly overrides the previous move, which just makes it jitter more.

i use .Heartbeat and it works just fine

okay so, here’s my totally perfect pathfinding code

note that the first block is from a module script so don’t worry about the return path

local success, errorMessage = pcall(function()
		path:ComputeAsync(startPosition, targetPosition)
	end)

	if not success then
		warn("Pathfinding failed: " .. errorMessage)
		return
	end

	local waypoints = path:GetWaypoints()

	if path.Status == Enum.PathStatus.Success and #waypoints > 0 then
		for i = 2, #waypoints do
			local waypoint = waypoints[i]

			if waypoint.Action == Enum.PathWaypointAction.Jump then
				Humanoid.Jump = true
			end

			Humanoid:MoveTo(waypoint.Position)
			local moveFinished = Humanoid.MoveToFinished:Wait()
		end    
		return path
	end

and then inside the pathfinding script i do this:

task.spawn(function() -- task.spawn so multiple enemies at a time can follow you, needs to be inside an ipairs loop, only do this if you're trying to handle every enemy with one script (which is what i'm doing)
					if closestPlayer then
						local targetPosition = closestPlayer.Character.Torso.PathfindPart.Position
						pathfindingModule.melee(humanoid, targetPosition)
					else
						humanoid:MoveTo(enemy.HumanoidRootPart.Position)
					end
				end)

so now if i am not wrong (i probably am) your code should look something like this (do note that i’m only giving you the way to pathfind, no player detection whatsoever):

for i, object in pairs(partsInRegion) do
		if object.Parent:FindFirstChild("Humanoid") then
			local route = pathFindingService:CreatePath()

			route:ComputeAsync(npcTorso.Position, object.Position)
			local waypoints = route:GetWaypoints()

-- indentations becuase i'm writing this on the website
			if route.Status == Enum.PathStatus.Success and #waypoints > 0 then
                 for i = 1, #waypoints do
                    local waypoint = waypoints[i]

                    if waypoint.Action == Enum.PathWaypointAction.Jump then
                        humanoid.Jump = true -- i'm not sure if this is the best way to initiate a jump
                    end   

                    humanoid:MoveTo(waypoint.Position)
                    humanoid.MoveToFinished:Wait()
                 end
            end

		end
	end

i can’t guarantee my code is the most optimal but it floats my boat

Just an FYI to anyone reading this.

1 Like