Help with a Pathfinding Zombie

  1. What do you want to achieve? Keep it simple and clear!
    A zombie that follows the nearest player using Pathfiding.

  2. What is the issue? Include screenshots / videos if possible!
    Finding a way to update the path when the player moves. When the closest player moves, the zombie is still pathfinding to the last position of the player’s PrimaryPart.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I haven’t really tried much since I’m new to Pathfinding.

local pathfindingService = game:GetService("PathfindingService")

local zombie = script.Parent
local humanoid = zombie.Humanoid

local searchRange = 20

local function getClosestPlayer()
	local closestDistance, closestPlayer = math.huge, nil
	
	for _, player in pairs(game:GetService("Players"):GetPlayers()) do
		if not player.Character or not player.Character.PrimaryPart then
			continue
		end
		
		local distance = (player.Character.PrimaryPart.Position - zombie.PrimaryPart.Position).Magnitude
		
		if distance <= searchRange and distance < closestDistance then
			closestDistance, closestPlayer = distance, player
		end
	end
	
	return closestPlayer
end

while true do
	local player = getClosestPlayer()
	
	if player then
		local path = pathfindingService:CreatePath()

		path:ComputeAsync(zombie.PrimaryPart.Position, player.Character.PrimaryPart.Position)

		for _, waypoint in pairs(path:GetWaypoints()) do
			humanoid:MoveTo(waypoint.Position)

			humanoid.MoveToFinished:Wait()
		end
	end
	
	wait(0.1)
end

the thing here is that the loop only restarts once the zombie went through each node of the path. instead, use a coroutine and stop the one that was running before:

local currentPath

while true do
	local player = getClosestPlayer()
	
	if currentPath then
		coroutine.yield(currentPath)
	end
	
	currentPath = coroutine.resume(coroutine.create(function()
		if player then
			local path = pathfindingService:CreatePath()

			path:ComputeAsync(zombie.PrimaryPart.Position, player.Character.PrimaryPart.Position)

			for _, waypoint in pairs(path:GetWaypoints()) do
				humanoid:MoveTo(waypoint.Position)

				humanoid.MoveToFinished:Wait()
			end
		end
	end))

	wait(0.1)
end
1 Like

Then should I stop the coroutine if the player moves?

It stops the coroutine every loop, so you don’t need to worry about that!

I get the error attempt to call a boolean value when I call the coroutine

what do you mean call the coroutine?

I added an extra () after the end) to call the coroutine

Don’t do that. the way you “call” a coroutine, is by using the coroutine.resume() function, which I already used.

Oh I thought it worked how coroutine.wrap did:

coroutine.wrap(function()
	print("hi")
end)()

I would try and fix this myself but I haven’t really used coroutine.create, resume, or yield. When I try what you suggested the zombie doesn’t move at all

print(coroutine.status(currentPath)) also prints the same error as earlier

you could change it to coroutine.wrap. I’ve never looked into it so I didn’t know it’s use, but now that I do, it looks pretty useful.

I really don’t know at this point. Sorry.

Ok, using coroutine.wrap is sort of the direction I wanted to go, but it keeps making the zombie backtrack. Thanks for the suggestion!

You’re definitely going to want to use coroutines, but you’ll need to find a way to incorporate them in a way that’ll work

What I need to do is restart the path every iteration of the while loop, so using yield and creating a new coroutine could work, but I’m not sure why it isn’t yielding

Edit: using prints on the script without the coroutine shows that it doesn’t make a new path until the previous one finishes, so I just need to figure out how to make a new path when it iterates through

Hello! A year passed since the last message in this thread, but I am working on the same Zombie Pathfinding AI right now and have the same issue. The main thing I have understand is that we must avoid

for _, waypoint in pairs (path:GetWaypoints()) do
end

at all costs. Because this is kinda tricky to stop the loop when player’s position has changed. I can recommend to replace this loop with a function that will check current player’s location after a zombie has reached a certain waypoint (or every single waypoint, depends on specifics of your AI). And if the position has changed you restart the loop and recompute the path. Also you need to change your

while true do

to something like

while wait (1) do

because the “while true do” eats a lot more resources. If a big amount of your zombies using this method consider putting the code into a ModuleScript. It will optimize the game and your code.