Pathfinding takes too long to update

So I made a zombie that follows player with pathfinding script but the problem is that it waits for the zombie to move to the first spot instead of following the player

Video:

If I remove hum.MoveToFinished:Wait() then it the pathfind stops working

Script:

repeat
	wait()
until script.Parent.Parent == workspace.Zombies

local Zombie = script.Parent
local PFS = game:GetService("PathfindingService")
local hum = script.Parent:WaitForChild("Zombie")
local RS = game:GetService("RunService")
local humrootpart = script.Parent:WaitForChild("HumanoidRootPart")
local path = PFS:CreatePath(
	{
		AgentRadius = 4,
		AgentHeight = 6,
		AgentCanJump = true,
		Costs = {
			Water = 20,
			Climb = 1
		}
	}
)
local target = nil
local status = require(script.Parent:WaitForChild("Status"))
local attackdebounce = false
local jumpdelay = true
local hithumR = nil

local function findTarget()
	local maxDistance = 999999
	for i, player in pairs(game.Players:GetPlayers()) do
		local char = player.Character or player.CharacterAdded:Wait()
		local humanoid = char:FindFirstChild("Humanoid")
		local magnitude = (humrootpart.Position - char.HumanoidRootPart.Position).Magnitude
		if magnitude <= maxDistance and char and humanoid.Health > 0 then
			maxDistance = magnitude
			target = char
		end
	end
	return target
end

local function jump()
	hum:ChangeState(Enum.HumanoidStateType.Jumping)
	wait(status.JumpDelay)
	jumpdelay = true
end

local function attack(target)
	local hithum = target:FindFirstChildWhichIsA("Humanoid")
	local hithumroot = target:FindFirstChild("HumanoidRootPart")
	if hithumroot then
		hithumR = hithumroot
		if (humrootpart.Position - hithumroot.Position).Magnitude < 4.5 then
			hum.WalkSpeed = 0
			hum.AutoRotate = false
			local hithum = target:FindFirstChildWhichIsA("Humanoid")
			if hithum then
				if hithum.Name ~= "Zombie" and attackdebounce == false and status.Dead ~= true and status.OnFire ~= true then
					attackdebounce = true
					hithum:TakeDamage(status.Damage)

					local hitsnd = math.random(1,2)
					if hitsnd == 1 then
						script.Parent.HumanoidRootPart.PunchSnds.SoundId = "rbxassetid://12366696098"
					elseif hitsnd == 2 then
						script.Parent.HumanoidRootPart.PunchSnds.SoundId = "rbxassetid://12366696960"
					end
					script.Parent.HumanoidRootPart.PunchSnds:Play()
					wait(status.AttackDelay)
					attackdebounce = false
				end
			end
			wait(1)
			hum.AutoRotate = true
			hum.WalkSpeed = status.WalkSpeed
		end
	end
end

while RS.Heartbeat:Wait() do
	findTarget()
	if target and status.Dead ~= true and status.Shoved == false then
		hum.WalkSpeed = status.WalkSpeed
		local temptarget = target:FindFirstChild("HumanoidRootPart")
		if temptarget and status.Dead ~= true then
			path:ComputeAsync(humrootpart.Position, temptarget.Position)
			waypoints = path:GetWaypoints()
			if path.Status == Enum.PathStatus.Success then
				for i, waypoint in pairs(waypoints) do
					if waypoint.Action == Enum.PathWaypointAction.Jump and jumpdelay == true then
						jumpdelay = false
						jump()
					end
					if hithumR then
						if (humrootpart.Position - hithumR.Position).Magnitude > 3 then
							hum:MoveTo(waypoint.Position)
							hum.MoveToFinished:Wait()
							
							local ZombieFolder = workspace.Zombies
							
							local raycastParams = RaycastParams.new()
							raycastParams.FilterDescendantsInstances = {ZombieFolder, Zombie}
							raycastParams.FilterType = Enum.RaycastFilterType.Exclude

							local ray = workspace:Raycast(humrootpart.Position, hithumR.Position, raycastParams)
							
							if ray and ray.Instance == hithumR then
								print("see you")
								print(ray.Instance)
								break
							else
								if ray then
									print(ray.Instance)
								end
								print("?")
							end
							
						else
							hum:MoveTo(humrootpart.Position)
						end
					end
					if status.OnFire ~= true then
						attack(target)
					end
				end
			end
		end
	elseif status.Dead ~= true then
		if status.Shoved == true then
			hum.WalkSpeed = 0
			hum:MoveTo(humrootpart.Position)
		else
			hum.WalkSpeed = status.WalkSpeed
			hum:MoveTo(humrootpart.Position)
		end
	end
end

Please help out, thank you!

1 Like

Remove every hum.MoveToFinished:Wait() part in the code you had just given.

1 Like

like I said

If I remove hum.MoveToFinished:Wait() then it the pathfind stops working

1 Like

This does not make any sense at all try removing the magnitude check if its greater than 10 or the check that checks if the magnitude is greater than 3.

1 Like

Yeah ok, now what? It’s still the same.

if (humrootpart.Position - hithumR.Position).Magnitude > 3 then
							hum:MoveTo(waypoint.Position + Vector3.new(math.random(-1,1),0,math.random(-1,1)))
							hum.MoveToFinished:Wait()
						else
							hum:MoveTo(humrootpart.Position)
							hum.MoveToFinished:Wait()
						end
1 Like

Remove that part completely and replace it with just:

hum:MoveTo(humrootpart.Position)
hum.MoveToFinished:Wait()

Also, isn’t this piece of code a bit redundant?

Since it just means that the player is not in range, in which, there is no need to chase after the player.

1 Like
hum:MoveTo(humrootpart.Position)
hum.MoveToFinished:Wait()

So you’re saying that the npc shouldn’t move at all??? Why???

Also, isn’t this piece of code a bit redundant?

I need the zombie to play the getting shoved animation, but I havent added it in yet

1 Like

The problem with your script is that you dont update the path midway. You need to either constantly generate a new path every x amount of time and cancel the old one, or use the simplepath module which is made for that same purpose.

1 Like

I know how to generate path but i dont know how to cancel or delete them

1 Like

What I’m trying to do is have a variable that increases by 1 every time and then creates a new variable set to the other one the function is called, so then after every time the script yields, it checks to make sure it never increased (increasing variable == oldvariable) and if it did, would return nil on the function, cancelling it.

1 Like

Try casting a ray in the direction from zombie to player to see if there is a clear path to the player every waypoint, if not then move to the next waypoint.

Something like:

for _, waypoint in pairs(waypoints) do
	humanoid:MoveTo(waypoint.Position)
	
	local ray = workspace:Raycast(humanoidRootPart.Position, direction)
	if ray and ray.Instance.Parent == target then
		break
	end
end
1 Like

Almost a solution, but the ray just doesn’t seem to hit even when I added params

Edited the script, still doesnt work. It’s In the header.

The second argument to raycasting has to be a direction, not a position.
To get the direction between two parts, you have to use (part2.Position - part1.Position).Unit

local raycastDistance = 1000
local direction = (hithumR.Position - humrootpart.Position).Unit

local ray = workspace:Raycast(humrootpart.Position, direction * raycastDistance, raycastParams)

Hope this helps!

2 Likes

I usually do it like this:

Create the path, move the enemy for lets say first 3 waypoints, then generate a new path and loop. also add a raycast to detect if there is no even need for a pathfind and just use moveto straight to the player

1 Like

Yeah I’m trying to do that aswell but I don’t know how to cancel path

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