[Solved] Pathfinding Problem

In that case, you can increase how “expensive” it thinks jumping is. Also, I just noticed in your code, you are not even setting your Agent Parameters?

pathParams is literally unused.

local pathParams = {
	AgentHeight = 6,
	AgentRadius = 2,
	AgentCanJump = true,
	
	Costs = {
		-- Jumping is now equivalent to walking 15 studs
		-- Increase this value further if they still prefer to 
		-- jump rather than walk
		Jump = 15
	}
}

local path = PathfindingService:CreatePath(pathParams)

local function getPath(destination)
	path:ComputeAsync(stranger.HumanoidRootPart.Position, destination.Position, pathParams)
	return path
end

There’s also no reason to call :CreatePath more than once if you’re never going to change your Parameters.

2 Likes

They are just going for the jump. They never ever try to take the correct path to the waypoints

Very interesting. This does completely prevent him from getting stuck. It does help a lot don’t get me wrong. But does it fix our problem? No. He still jumps up there instead of taking the other way around

If you set AgentCanJump to false, does the NPC take the route you want it to take?

1 Like

Yes. We are getting close. Fully solved the waypoints problem. Now how do we fix the attack? I have no clue how to pathfind to targets.

Continuous pathfinding is very annoying and complicated and I would recommend you just use something like SimplePath:

Then, you can just do path:Run(target.HumanoidRootPart.Position) in your attack function, and get rid of your pathfinding for-loop.

1 Like

That’s your opinion. I would really like to replace the attack function with your pathfinding version of it so I can solve this problem for good and mark your answer as solution. If you could please annotate how it works so everyone can understand it, would be a huge help to all of us.

Here is a modified version of your code using SimplePath for pathfinding.

local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local stranger = script.Parent
local humanoid = stranger.Humanoid
local rootPart = stranger.HumanoidRootPart

local raycastParams = RaycastParams.new()

local pathParams = {
	AgentHeight = 6,
	AgentRadius = 2,
	AgentCanJump = true,
	Costs = {
		-- Jumping is equivalent to walking 50 studs
		Jump = 50
	}
}

-- Create our Path with SimplePath
local path = require(script.SimplePath).new(stranger, pathParams)

stranger.PrimaryPart:SetNetworkOwner(nil)

raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = { stranger }

local function canSeeTarget(target)
	local direction = target.HumanoidRootPart.Position - rootPart.Position

	local result = workspace:Raycast(rootPart.Position, direction, raycastParams)

	if result then
		local hit = result.Instance
		if hit and hit:IsDescendantOf(target) then
			-- Something was in the way, but it was just our Target
			return true
		else
			-- Something was in the way, but it wasn't our Target
			return false
		end
	else
		-- Nothing in the way
		return true
	end
end

local function findTarget()
	local players = Players:GetPlayers()
	local nearestTarget = nil
	local maxDistance = 75
	
	for _, player in players do
		local target = player.Character
		
		if target and target.PrimaryPart then
			local target = player.Character
			local distance = (rootPart.Position - target.HumanoidRootPart.Position).Magnitude
			
			if distance < maxDistance and canSeeTarget(target) then 
				nearestTarget = target
				maxDistance = distance
			end
		end
	end

	return nearestTarget
end

local function attack(target)
	local distance = (rootPart.Position - target.HumanoidRootPart.Position).Magnitude

	if distance > 3 then
		path:Run(target.HumanoidRootPart.Position)
	else
		target.Humanoid.Health = 0
	end
end

local function patrol()
	-- Recognize targets
	local target = findTarget()
	
	if target then
		attack(target)
		-- Don't worry about patrolling when we're hunting someone down
		return
	end
	
	-- "Idle" means we are not moving.
	-- When `path:Run` is called, it sets it's `Status` to
	-- "Active". Then, when the Destination is reached, it is set back to "Idle".
	-- We don't want to change which Waypoint we're moving towards while
	-- we are moving towards it, so we can use `Status` to make sure we
	-- stick to 1 Waypoint
	if path.Status == "Idle" then
		local waypoints = workspace.Waypoints:GetChildren()
		local randomNum = math.random(1, #waypoints)
		
		path:Run(waypoints[randomNum].Position)
	end
end

while true do
	patrol()
	-- There's no point updating every frame, so it's just an
	-- easy performance optimization that won't have any impact besides
	-- a very small "reaction time" that you probably won't even notice.
	task.wait(0.2)
end
1 Like

I guess I have no choice but to try this. I immediately encountered problems after trying to use the continuous pathfinding

1 Like

Line 101 is calling :Run and giving it something that doesn’t have a position. What is on Line 101?

path:Run(waypoints.Position)
1 Like

Oops :grimacing: That should be

path:Run(waypoints[randomNum].Position)

Every single time I think that I’ve finally fixed everything, nope. It gets stuck the same way every single time I move my npc out far out enough. It’s funny how even just in my super basic game that has barely anything in it, things still don’t even work right. I will send a video.

Are there any errors in the Output?

There are 0 errors in the Output

(character limit)

You didn’t change any of the code, right?

Add some code underneath this:

-- Create our Path with SimplePath
local path = require(script.SimplePath).new(stranger, pathParams)

path.Error:Connect(function(ErrorType)
    warn(`Could not pathfind: {ErrorType}`)
end)

Check the Output when you get to the same issue with the new code.

1 Like

Computation Errors

Change your attack function:

local function attack(target)
	local distance = (rootPart.Position - target.HumanoidRootPart.Position).Magnitude
	
	if distance > 3 then
		local targetPosition = target.HumanoidRootPart.Position
		
		local success = path:Run(targetPosition)
		
		if not success then
			humanoid:MoveTo(targetPosition)
		end
	else
		target.Humanoid.Health = 0
	end
end

I’m not entirely sure what could be causing it, but this should at least mean the NPC won’t freeze in it’s tracks if something goes wrong.