Pathfinding, NPC tends to stop at brief moments, as well as a slight delay to the movement

Since yesterday I’ve been looking at articles and videos on Pathfinding since I never used it, today I implemented a version of yellow mustangs Pathfinding AI, except I converted it into a module and made the spawning of the zombies wrapped under a thread, his method was to clone a script under each NPC, so I assume this was the better approach, now the problem I’ve been having is the NPCs seem to have a slight delay movement and I’d like to assume it’s because of the time out, I even tested it without any sort of animations in this case walking, it still seemed to have a delay in movement, also at times it keeps going in the right path for 1-2 seconds, I just don’t simply like the implementation and my main question is if there is a alternative method, or a better method to Pathfinding since I am very dumb founded, I’ve looked at many articles on the DevFourm post about Pathfinding’s optimization viewpoint and many say it’s well optimized, it’s just the way one implements it, so if anyone can maybe give me an Idea on why that would help, I can also send relevant parts of the code if needed!

Video of the issue:

1 Like

Could you provide the code handling NPC movement/pathfinding?

function CheckSight(ZombieRoot, TargetRoot)
	local RayParams = RaycastParams.new()
	RayParams.FilterDescendantsInstances = {ZombieRoot.Parent}
	RayParams.FilterType = Enum.RaycastFilterType.Blacklist

	local CreateRay = workspace:Raycast(ZombieRoot.Position, (TargetRoot.Position - ZombieRoot.Position).Unit * 35, RayParams)
	if CreateRay then
		local PartHit, Position = CreateRay.Instance, CreateRay.Position 
		if PartHit:IsDescendantOf(TargetRoot.Parent) and math.abs(PartHit.Position.Y - ZombieRoot.Position.Y) < 3 then
		--	print("I can see the target")
			return true
		end
	end
	return false
end

function CreatePathway(ZombieRoot, TargetRoot) -- Target is the HumanoidRootPart, as well the Zombie
	local Path = PathfindingService:CreatePath()
	local ZombieHumanoid = ZombieRoot.Parent.Humanoid
	local TargetHumanoid = TargetRoot.Parent.Humanoid

	Path:ComputeAsync(ZombieRoot.Position, TargetRoot.Position)

	local Waypoints = Path:GetWaypoints()

	if Path.Status == Enum.PathStatus.Success then
		for _, Waypoint in ipairs(Waypoints) do
			ZombieHumanoid:MoveTo(Waypoint.Position)
			local TimeOut = ZombieHumanoid.MoveToFinished:Wait(1)
			if not TimeOut then
			--	print("Path took too long")
				CreatePathway(ZombieRoot, TargetRoot)
				break;
			end
			if CheckSight(ZombieRoot, TargetRoot) then
				repeat
				--	print("Moving directly into the target")
					ZombieHumanoid:MoveTo(TargetRoot.Position)
				--	AttackTarget(ZombieRoot, TargetRoot)
					wait()
					if TargetRoot == nil then
						break;
					elseif TargetRoot.Parent == nil then
						break;
					end
				until CheckSight(ZombieRoot, TargetRoot) == false or ZombieHumanoid.Health < 1 or TargetHumanoid.Health < 1
				break;
			end
			if (ZombieRoot.Position - Waypoints[1].Position).Magnitude > 10 then
			--	print("Target has moved, generating new path")
				CreatePathway(ZombieRoot, TargetRoot)
				break;
			end
		end
	end
end

local RunService = game:GetService("RunService")

function UndeadAI.TargetPlayers(Zombie)
	local ZombieRoot = Zombie.HumanoidRootPart
	
	Zombie.Humanoid.Died:Connect(function()
		game.Debris:AddItem(Zombie, 1)
	end)
	
	repeat wait(0.1)
		local TargetRoot = FindTarget(ZombieRoot)
		if TargetRoot and TargetRoot.Parent then
			CreatePathway(ZombieRoot, TargetRoot)
		end  
	until Zombie.Humanoid.Health < 1	
end

Take a look at my pathfinding module. This module handles all the problems or errors you are facing with your script. Furthermore, you can easily code what you did there in the video with just a few lines using the module.

Set Network owner to nil

script.Parent.PrimaryPart:SetNetworkOwner(nil)

Make sure NPCs primary part is set to HumanoidRootPart, if not then use this.

script.Parent.PrimaryPart = script.Parent:WaitForChild("HumanoidRootPart")
script.Parent.PrimaryPart:SetNetworkOwner(nil)

I did take a look at your module, but the same problem goes here, no matter what pathfinding has a delay to compute a path, also I forgot to mention yellow mustang actually had a updated AI for multiple NPCs and it’s working way better than this, anyways thanks for the suggestion!

I already did it that off the script, I set it the server as the NetworkOwner when the NPC was being cloned, anyways like I stated above, the code was updated using yellow mustangs updated version for multiple NPCs.

The code has been updated using yellow mustangs new multiple NPC AI which is working fine for me, thanks everyone who took time to reply, you can find his tutorial on youtube!

It looks as if the zombie is trying to find a way past the other zombies. Maybe you should change your code so it doesn’t attempt this?

edit:

Looks like I’m a minute late. Glad you found a solution!

Yes I did, and no the thing is the zombies are all cloned under a Folder named “Zombies” just for them, also the only target they’re targeting are players, since I didn’t include it in the code, my pardon, it only loops through GetPlayers() in which than I reference there characters, etc. But yes I did find a solution thanks to yellow mustang which uses collection service and a better usage of threads to calculate the path, target, etc!