Constantly pathfind to the player without stutter?

I am making a horror game with a monster that is constantly chasing you. Right now I am having it pathfind to the player constantly, however it stutters a lot and gets stuck on trees too much. Is there anything I can do?
Code:

while wait() do
	local destination = findDestination()
	local dist = getDist()
	if destination then
		--print(dist)
		if dist <= speedDist then
			humanoid.WalkSpeed = dfWalkspeed + plusSpeed
			--print("RUN")
		else
			humanoid.WalkSpeed = dfWalkspeed
		end
		path:ComputeAsync(root.Position, destination.Position)
		local waypoints = path:GetWaypoints()
		pcall(function()
			if waypoints[3].Action == Enum.PathWaypointAction.Jump then
				humanoid.Jump = true
			end
			if waypoints[3] then
				humanoid:MoveTo(waypoints[3].Position)
			else
				humanoid:MoveTo(root.CFrame.LookVector*-5)
				humanoid.MoveToFinished:Wait()
			end
			--humanoid.MoveToFinished:Wait()
		end)
	end
end

I heard from a tutorial that you have to set the npcs primary network owner to nil.
Use this code snippet:

script.Parent.PrimaryPart:SetNetworkOwner(nil)
1 Like

That’s already apart of my code at the top of the script. Still stutters.

1 Like

Oh, my bad. I didn’t see it.
Could you send the video of the npc studdering with and without the

humanoid.MoveToFinished:Wait()

you have there?

Here you go: 2021-12-07 18-05-57

have you tested this script with a regular default roblox avatar?
if so, and it works fine on that rig, it might be a rig issue for your rig your currently using

Instead of using a while loop you should be connecting repeating code to a RunService event, specifically Heartbeat.

wait() creates a 2 frame delay window between executions of the loop, you can decrease this to 1 frame by using task.wait() instead.

Heartbeat and Stepped as the above suggested would also be valid.

Before I even was making this game I was experimenting with regular rigs and an old version of the script I have now, same issue.

Will definitely try this! I hope it helps!

It didn’t work sorry :frowning_face: tried exactly that, still stutters. I’m beginning to wonder if the whole network ownership deal is to blame…

I had this same issue and eventually gave up solving it, No matter what I set the network ownership to it still stutters.

Piggy’s bots pathfind don’t they? They don’t seem to stutter, although it has been a while since I’ve played.

1 Like

They don’t stutter, mini toon is an amazing dev. I imagine that there is a way to solve this I just haven’t found it yet,

Well I have a tip that made it run smooth-er but it still lags every once in a while. Although I don’t know whether or not that’s related to me using .Heartbeat now. Tip: Use script.Parent.PrimaryPart:CanSetNetworkOwner(true)

1 Like

Your script doesn’t contain 1/2 of what you need to pathfind.

This script uses a modual script. Any bot you want to use it requires it. It’s un-copylocked

Hike Ball - Roblox

What does your script do different from mine? If you want the full script, here it is full script - Pastebin.com

The routines where written by KingSomebody… They work. A ReadME explains why you usualy want to go to every-other waypoint.

This one patrols…

If chasing a Player I would just go two poins away and then call another pathfind.

I wrote the Read Path routine: You must hadle any errors it returns. I have some clumsy hadeling of some which I am sure that you can improve on…

We stand on the shoulders of giants…

function ReturnPath(start, finish, MaxDist)

local path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
print (path.Status)

if path.Status == Enum.PathStatus.FailFinishNotEmpty then
	local dist = (finish - start).magnitude
	while dist > 8 and path.Status == Enum.PathStatus.FailFinishNotEmpty do

wait()
finish = start + (finish - start)/1.5
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
dist = (finish - start).magnitude

		local part = Instance.new("Part", Workspace)

	part.FormFactor = Enum.FormFactor.Custom
	part.Size = Vector3.new(4,4,4)
	part.CFrame = CFrame.new(finish)
	part.Shape = "Ball"
	part.Anchored = true
	part.CanCollide = false
	part.BrickColor = BrickColor.Red() 
	table.insert(Showed, part)

	end -- room to manuveur?
	Bot.ShowPath (start, finish)
end -- finish error

if path.Status == Enum.PathStatus.FailStartNotEmpty
or 	   path.Status == Enum.PathStatus.ClosestNoPath	then

wait()
start = start + Vector3.new(0,0,4)
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)

	if  path.Status == Enum.PathStatus.FailStartNotEmpty
	or  path.Status == Enum.PathStatus.ClosestNoPath then
		start = start + Vector3.new(4,0,-4)
		path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
	end
	if  path.Status == Enum.PathStatus.FailStartNotEmpty
		or  path.Status == Enum.PathStatus.ClosestNoPath  then
		start = start + Vector3.new(-4,0,-4)
		path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
	end
		
	if  path.Status == Enum.PathStatus.FailStartNotEmpty
		or  path.Status == Enum.PathStatus.ClosestNoPath  then
		start = start + Vector3.new(-4,0,-4)
		path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
	end
	
	Hum:MoveTo(start)

wait()

end -- start error?

return path
end–Return Path

The formatting is broken, and also right now I’m trying to focus on why it’s stuttering. It’s like the biggest issue at the moment.

It is stuttering, because you are not waiting to get to a waypoint b4 aiming for the next, almost imediately.

Just go to the page and modify the script to your liking…

Bot.FindPath = function(finish, PointM, MaxPoint, MaxDist)
local MaxPoint = MaxPoint or 1
local PointM = PointM or 1
local MaxDist = MaxDist or 100
local Am = 1

local path = ReturnPath(Tor.Position, finish, MaxDist)	

– local path = pathfinding:ComputeRawPathAsync(Tor.Position, finish, MaxDist)

local points = path:GetPointCoordinates()

local Impeded = nil
local LastDist = -1	-- Initialize old Distance
local skip = false
local ListEnd = #points

for i, point in pairs(points) do
	if Am == PointM then
		local j = 24 -- deadman's clutch
					
		if not skip or i == ListEnd then-- hack for diagonal - Reduces resolution/accuracy by half though...

Hum:MoveTo(point + (point - Tor.Position).unit)
–skip = true

			if Tor.Position.y < point.y - 4 then  -- If next point is more than 5 studs above us
				Hum.Jump = true 
			end 
			
			repeat
				  j = j - 1
				wait(.07) -- better place for wait; before measuring distance: Old way had old informatin for "Until" check.
				TorP = Tor.Position
				distance = (Vector3.new(point.x, TorP.y, point.z) - TorP).magnitude -- are-we-there-yet
		
				Impeded = math.abs(distance - LastDist)
				LastDist = distance

			until distance < 2.3 or Impeded < .002 or j < 1  -- Impeded: a way-out of logic for Bot,who is at an impass.
		
		else
			skip = false
		end -- Diagonal?

if j < 1 then
print (“Too Long in get-there loop”)
Hum.Jump = true
end

		if Impeded < .001 then -- 'Impeded' accuarcy.
			Hum.Jump = true  -- Jump to get-up high stairs (risers).
		
		end -- Impeded?

	end -- Am
	
	if Am == MaxPoint then
		Am = 1
	else
		Am = Am + 1
	end
	
end -- for

end – func

Bot.FindDynamicPath = function(finish)
local path = pathfinding:ComputeRawPathAsync(Tor.Position, finish, 500)
local points = path:GetPointCoordinates()
local point = points[1]
if point then
Hum:MoveTo(point)
repeat
distance = (point - Tor.Position).magnitude
wait()
until distance < 3
Bot.FindDynamicPath(finish)
end
end

Bot.ShowPath = function(start, finish)
local path = pathfinding:ComputeRawPathAsync(start, finish, 500)
local points = path:GetPointCoordinates()
for _, point in pairs(points) do
local part = Instance.new(“Part”, Workspace)
part.FormFactor = Enum.FormFactor.Custom
part.Size = Vector3.new(2,2,2)
part.CFrame = CFrame.new(point)
part.Anchored = true
part.CanCollide = false
part.BrickColor = BrickColor.Blue()
table.insert(Showed, part)
end
end

Bot.ClearPaths = function()
for i,v in pairs(Showed) do
v:Destroy()
Showed[i] = nil
end
end

Bot.GetBackwardsCoordinates = function(Path)
local BackPath = {}
local points = Path:GetPointCoordinates()
for i = NumTab(points), 1, -1 do
table.insert(BackPath, points[1])
end
return BackPath
end

Bot.GetBackwardsPath = function(Path)
local points = Path:GetPointCoordinates()
local finish = points[1]
local start = points[#points]
return pathfinding:ComputeRawPathAsync(start, finish, 500)
end

Bot.MovePlayer = function(Player, finish)
local Char = Player.Character
local Tor = Char.Torso
local Hum = Char.Humanoid
local path = pathfinding:ComputeRawPathAsync(Tor.Position, finish, 500)
local points = path:GetPointCoordinates()
local point = points[1]
if point then
Hum:MoveTo(point)
repeat
distance = (point - Tor.Position).magnitude
wait()
until distance < 3
Bot.MovePlayer(Player, finish)
end
end

return Bot