NPC follows me and falls off the map after I get flinged off the map

My NPC keeps following me and falling off when I get flinged off the map (like hitting the victim and the victim gets flinged to the edge)

Here is the script:
Oh and by the way, this script is named Pathfinding and it is parented to AI folder, and that AI folder is parented onto the NPC.

The hierarchy is: NPC → AI → Pathfinding

local debugMode = false
local targetNPCs = false

local h = script.Parent.Parent:WaitForChild("Humanoid")
local pathService = game:GetService("PathfindingService")
local targetV = script.Parent:WaitForChild("Target")

function closestTargetAndPath()
	local humanoids = {}
	if targetNPCs then
		local function recurse(o)
			for _,obj in pairs(o:GetChildren()) do
				if obj:IsA("Model") then
					if obj:findFirstChild("Humanoid") and obj:findFirstChild("Torso") and obj.Humanoid ~= h and obj.Humanoid.Health > 0 and not obj:findFirstChild("ForceField") then
						table.insert(humanoids,obj.Humanoid)
					end
				end
				recurse(obj)
			end
		end
		recurse(workspace)
	else
		for _,v in pairs(game.Players:GetPlayers()) do
			if v.Character and v.Character:findFirstChild("HumanoidRootPart") and v.Character:findFirstChild("Humanoid") and v.Character.Humanoid.Health > 0 and not v:findFirstChild("ForceField") then
				table.insert(humanoids,v.Character.Humanoid)
			end
		end
	end
	local closest,path,dist
	for _,humanoid in pairs(humanoids) do
		local myPath = pathService:ComputeRawPathAsync(h.Torso.Position,humanoid.Torso.Position,500)
		if myPath.Status ~= Enum.PathStatus.FailFinishNotEmpty then
			-- Now that we have a successful path, we need to figure out how far we need to actually travel to reach this point.
			local myDist = 0
			local previous = h.Torso.Position
			for _,point in pairs(myPath:GetPointCoordinates()) do
				myDist = myDist + (point-previous).magnitude
				previous = point
			end
			if not dist or myDist < dist then -- if true, this is the closest path so far.
				closest = humanoid
				path = myPath
				dist = myDist
			end
		end
	end
	return closest,path
end

function goToPos(loc)
	h:MoveTo(loc)
	local distance = (loc-h.Torso.Position).magnitude
	local start = tick()
	while distance > 4 do
		if tick()-start > distance/h.WalkSpeed then -- Something may have gone wrong. Just break.
			break
		end
		distance = (loc-h.Torso.Position).magnitude
		wait()
	end
end

while wait() do
	local target,path = closestTargetAndPath()
	local didBreak = false
	local targetStart
	if target and h.Torso then
		targetV.Value = target
		targetStart = target.Torso.Position
		roaming = false
		local previous = h.Torso.Position
		local points = path:GetPointCoordinates()
		local s = #points > 1 and 2 or 1
		for i = s,#points do
			local point = points[i]
			if didBreak then 
				break
			end
			if target and target.Torso and target.Health > 0 then
				if (target.Torso.Position-targetStart).magnitude < 1.5 then
					local pos = previous:lerp(point,.5)
					local moveDir = ((pos - h.Torso.Position).unit * 2)
					goToPos(previous:lerp(point,.5))
					previous = point
				end
			else
				didBreak = true
				break
			end
		end
	else
		targetV.Value = nil
	end
	if not didBreak and targetStart then
		goToPos(targetStart)
	end
end

Help me fix this falling off problem.

Edit: it had a lot of errors

Anything with while wait() do is probably wrong. This will continue execution whether your logic in locally defined and called functions is correct. The timing of execution in this loop may outrun the logic in internally called functions and possibly create race conditions between cause and outcome. When functions are called inside such tight loops, they won’t wait for return conditions but continue hammering the internal logic because the loop timer is so tight. Maybe using a connect/disconnect system to a better timing system like BindToRenderStep will help. At least then you can better control the onset and reset of play mechanics.

im a new programmer so i dont really understand runservice because the only thing that comes to my head is while true do or while task.wait() do

but i do understand using renderstepped as it runs every frame

Actually, after some tests, it seems a tight loop will always wait for return of a function to finish execution. So timing is probably not an issue, or a racing of logic. I would say though, the undesired behaviour of the NPC is bourne from the tight loop and its unending logic. You may need a stop/start mechansim when a certain threshold is met (i.e. player is flung) so that the loop does not continue to process movements for the NPC. That’s why I would lose the loop and have a stop/start mechanism on the NPC’s movement logic that is linked to the players position/condition/out-of-map-bounds etc…

Edit: i have found the solution with a different script

The humanoid is probably nil, try waiting for it:

		local hum = char and char:FindFirstChild("HumanoidRootPart");
		if not hum then continue end;
		local mag = (Zombie.HumanoidRootPart.Position - hum.Position).Magnitude

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