Pathfinding AI can't catch player

I’ve been trying to create a pathfinding script that’ll chase the nearest player for the past two days, and it’s been successful for the most part (especially considering this is my first time seriously messing with it). However, I’m stumped when it comes to the problem I discovered a few hours ago.

The problem is that the ai seems to have its final waypoint as the player’s previous position, making it stop for just a moment. This makes it look stuttery and makes it impossible for the ai to catch the player if they’re moving when it should as it is faster than the player.

Here’s a video of the issue in question:

I suspect the issue arises from the path being computer in the while loop. However, I’ve tried to remove it from the while loop and can’t seem to even make the ai move after doing so. I’ve tried a whole bunch of other solutions that did not have any different effect either.

Here is my script:

Pathfinding Script
local human = script.Parent:WaitForChild("Humanoid")
local humanRootPart = script.Parent:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local Path = PathfindingService:CreatePath()
script.Parent.PrimaryPart:SetNetworkOwner(nil)

local moving = false

local function findTarget()
	local Players = game:GetService("Players")
	local MAX_DISTANCE = 200
	local nearestTarget
	
	for index, player in pairs(Players:GetPlayers()) do
		if player.Character then
			local target = player.Character
			local distance = (humanRootPart.Position - target.HumanoidRootPart.Position).magnitude
			
			if distance < MAX_DISTANCE then
				nearestTarget = target
				MAX_DISTANCE = distance
			end
		end
	end
	
	return nearestTarget
end

local currentWaypointIndex = 0
local waypoints = {}
local function moveToNextWaypoint()
	currentWaypointIndex += 1
	if currentWaypointIndex > #waypoints then
		moving = false
		return
	end	
	
	if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
		human:ChangeState(Enum.HumanoidStateType.Jumping)
	end
	
	human:MoveTo(waypoints[currentWaypointIndex].Position)
end
human.MoveToFinished:Connect(moveToNextWaypoint)



while true do
	local target = findTarget()
	if target ~= nil then
		local targetPos = target.PrimaryPart.Position
		Path:ComputeAsync(humanRootPart.Position, targetPos)
	
		currentWaypointIndex = 1
		waypoints = Path:GetWaypoints()
		
		if moving == false then
			moving = true
			moveToNextWaypoint()
		end
	else
		if currentWaypointIndex >= 1 then
			moving = false
			waypoints = {}
			currentWaypointIndex = 0
		end
		wait()
	end
end

Any help is very much appreciated!

2 Likes

I have no idea how to create any type of AI that relates to this, but instead of bringing the AIs character to the back of the player, you could perhaps change the script to make it get to the nearest players humanoid location instead?

Sorry, I’m not really sure I understand what you mean.

The AI already is set to travel to the nearest player’s HumanoidRootPart, I can’t really think of what else you mean. Again, sorry I don’t understand.

2 Likes

I’m gonna give up for tonight since I’ve been at this for a couple of hours now with a few short breaks. I’ll leave a link to this post here for myself to see in the morning.

Tried it out using R15, the short pause stopped but the character seems to jump now Instead maybe it’s detecting the leg as an obstacle and recalculates the path which causes the stop? I honestly have no Idea of Path finding though. Hope you’ll find the error!

I’ve had this issue in the past, and this worked for me:

You could try and extend the Target Position to the front of the Target’s HumanoidRootPart a few studs.

Example:

local TargetPosition = TargetRoot.CFrame + (TargetRoot.CFrame.LookVector * 3) -- "3" could be based on the Target's WalkSpeed.

This should solve your issue.

3 Likes

This is not a pathfinding script.

You can find several by searching this forum. and the library. Mod one that works…

Hike Ball - Roblox

Speed AI by RealAi Inc. - Brains 4 Zombies - Roblox

Will this work, Doesn’t wait() default to 1 - 0.1 seconds?

local human = script.Parent:WaitForChild("Humanoid")
local humanRootPart = script.Parent:WaitForChild("HumanoidRootPart")
local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")
local Path = PathfindingService:CreatePath()
script.Parent.PrimaryPart:SetNetworkOwner(nil)

local moving = false

local function findTarget()
	local Players = game:GetService("Players")
	local MAX_DISTANCE = 200
	local nearestTarget

	for index, player in pairs(Players:GetPlayers()) do
		if player.Character then
			local target = player.Character
			local distance = (humanRootPart.Position - target.HumanoidRootPart.Position).magnitude

			if distance < MAX_DISTANCE then
				nearestTarget = target
				MAX_DISTANCE = distance
			end
		end
	end

	return nearestTarget
end

local currentWaypointIndex = 0
local waypoints = {}
local function moveToNextWaypoint()
	currentWaypointIndex += 1
	if currentWaypointIndex > #waypoints then
		moving = false
		return
	end	

	if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
		human:ChangeState(Enum.HumanoidStateType.Jumping)
	end

	human:MoveTo(waypoints[currentWaypointIndex].Position)
end
human.MoveToFinished:Connect(moveToNextWaypoint)



RunService.Stepped:Connect(function()
	local target = findTarget()
	if target ~= nil then
		local targetPos = target.PrimaryPart.Position
		Path:ComputeAsync(humanRootPart.Position, targetPos)

		currentWaypointIndex = 1
		waypoints = Path:GetWaypoints()

		if moving == false then
			moving = true
			moveToNextWaypoint()
		end
	else
		if currentWaypointIndex >= 1 then
			moving = false
			waypoints = {}
			currentWaypointIndex = 0
		end
	end
end)

Nope, that just makes the AI lag behind even more because it has to compute even more frequently.

Then make a cooldown(create a special thread for path generating) for creating a new path and if the path doesn’t exist then just follow the player instead of points.
So after the global value of path will be loaded just tell the pathfinding to find closest points to the creature and player.
Find closest point which isn’t intersecting with the creature’s distance between player.
And don’t change the direction sharply, it looks unrealistic
image
Get all points in the yellow area and find the closest one to the chaser (chaser is red and the player is blue)

set HumanoidRootPart’s network owner to nil