Npc player tracking system stuttering and glitching

As you can probably tell, I am trying to achieve something simple, an NPC that is able to follow the closest player. This part works perfectly, but unfortunately, I’ve had a problem.

The NPC stutters while running after the player. Sometimes it stops stuttering and then starts again but I’m not sure if that is relevant. I think this problem is allied with the Renderstepped and MoveTo events/functions. Please let me know what you think.

Part of tScript:

local heartbeat = RunService.Heartbeat:Connect(function()
		task.wait()
		local players = game.Players:GetPlayers()
		for i,enemy in pairs(self.Models) do
			enemy.Parent = workspace
			local target = nil
			local minValue = nil
			for i,player in pairs(players) do
				local char = player.Character
				local distance = (enemy.HumanoidRootPart.CFrame.Position - char.HumanoidRootPart.CFrame.Position).magnitude
				if minValue == nil then
					minValue = distance
					target = char
					print("min value hahahhaa " .. minValue)
					print("target lol" .. target.Name)
				else
					if minValue > distance then
						minValue = math.min(minValue, distance)
						target = char
					else
						print("nonono")
					end
					print(distance)
					print(minValue)
					print(target)
				end
			end
			enemy.Humanoid:MoveTo(target.HumanoidRootPart.Position)
		end
	end)

Use the roblox’s :moveTo example code and change it a bit:

local function moveTo(humanoid, targetPoint, andThen)
	local targetReached = false

	-- listen for the humanoid reaching its target
	local connection
	connection = humanoid.MoveToFinished:Connect(function(reached)
		targetReached = true
		connection:Disconnect()
		connection = nil
		if andThen then
			andThen(reached)
		end
	end)

	-- start walking
	humanoid:MoveTo(targetPoint)

	-- execute on a new thread so as to not yield function
	task.spawn(function()
		while not targetReached do
			-- does the humanoid still exist?
			if not (humanoid and humanoid.Parent) then
				break
			end
			-- has the target changed?
			if humanoid.WalkToPoint ~= targetPoint then
				break
			end
			-- refresh the timeout
			humanoid:MoveTo(targetPoint)
			task.wait(6)
		end

		-- disconnect the connection if it is still connected
		if connection then
			connection:Disconnect()
			connection = nil
		end
	end)
end

local function andThen(reached)
	print((reached and "Destination reached!") or "Failed to reach destination!")
end

moveTo(script.Parent:WaitForChild("Humanoid"), Vector3.new(50, 0, 50), andThen)

Try creating a ray. For example:

--If the enemy's stud is less than the distance then
if (enemy.HRP.Position - char.Humanoid.Position).magnitude < distance then
	target = enemy.HRP
	
	--Create Ray
	local origin = char.Humanoid.Position -- Origin of the ray
	local direction = enemy.HRP.Position - char.Humanoid.Position -- direction of the ray
	local params = RaycastParams.new() --Ray cast params
	params.FilterDescendantsInstances = {script.Parent}
	params.FilterType = Enum.RaycastFilterType.Blacklist
	
	local ray = workspace:Raycast(origin, direction,params)
	
	if ray then
		char:MoveTo(target.Position) --If ray, then the character will move to the target 
	end
end

I’ll definitely look into this script right here and make a few modifications to make the NPC constantly follow the player without any delay.

Just got one question, what am I supposed to pass in the andThen parameter?

edit: nevermind what a dumb question, I just had to pass the function

Did it work? I’d love to know and if it did could you close the post.

try setting the networkowner of all the baseparts of the npc to nil

for i,v in pairs(npc:GetDescendants()) do
    if v:IsA("BasePart") then
        v:SetNetworkOwner(nil)
    end
end
3 Likes

Thank you, I was reading about network ownership last night because I’ve never really used it before. Turns out it works perfectly, cheers!

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