PathfindingService is making NPC jump off the edge of map instead of chasing player

Wait but how would I make it keep making a path for the NPC to follow?

Is it another while wait(3) do?

Does this work?

local npcHRP = script.Parent.HumanoidRootPart

local PathFindingServ = game:GetService("PathfindingService")

local npcH = script.Parent.Humanoid
local npcT = script.Parent.Torso

local function GetNearestPlayer(minimumDistance)
    local closestMagnitude = minimumDistance or math.huge
    --minimumDistance is a number in studs
    local closestPlayer
    for i,v in next, game.Players:GetPlayers() do
		local Character = v.Character
		if (Character) then
			local humanoid = Character.Humanoid
			local HRP = Character.HumanoidRootPart
			if (humanoid.Health > 0) then
				local mag = (npcHRP.Position - HRP.Position).Magnitude
				if (mag <= closestMagnitude) then
					closestPlayer = v
					closestMagnitude = mag
				end
			end
		end
	end
	return closestPlayer
end

local closestPlayer = GetNearestPlayer(70)

local newThing = coroutine.create(function()
	while wait(3) do
		closestPlayer = GetNearestPlayer(70)
	end
end)

local newPath = coroutine.create(function(path)
	while wait(3) do
		path:ComputeAsync(npcT.Position, closestPlayer:WaitForChild("Character").HumanoidRootPart.Position)
	end
end)

coroutine.resume(newThing)

local path = PathFindingServ:CreatePath()

coroutine.resume(newPath(path))

local waypoints = path:GetWaypoints()
for _, wp in pairs(waypoints) do
	if wp.Action == Enum.PathWaypointAction.Jump then
		script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
	end
	print(wp.Action)
	script.Parent.Humanoid:Move(wp.Position)
	script.Parent.Humanoid.MoveToFinished:Wait()
end

Nope it doesn’t.

line 47: attempt to call a thread value

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

local path = PathfindingService:CreatePath()

local function getClosestPlayer(position)
    local players = Players:GetPlayers()
    local closestDistance, closestPosition, closestPlayer = math.huge, nil, nil

    for i, player in ipairs(players) do
        if not player.Character then continue end

        local playerPosition = player.Character:GetPrimaryPartCFrame()
        local distance = (playerPosition.Position - position).Magnitude

        if distance < closestDistance then
            closestDistance = distance
            closestPosition = playerPosition.Position
            closestPlayer = player
        end
    end

    return closestPlayer, closestPosition
end

while wait(<arbitrary number here>) do
    local currentPosition = <NPCs Vector3 pos here>
    local closestPlayer, closestPosition = getClosestPlayercurrentPosition)
    
    path:ComputeAsync(currentPosition, closestPosition)
    if path.Status == Enum.PathStatus.Success then
        local waypoints = path:GetWaypoints()
        local currentWaypoint = 0

        path.Blocked:Connect(function(index)
            if index >= currentWaypoint then
                -- recompute path
            end
        end)
    else
        -- recompute path
    end
end
1 Like

How would I re-compute it? Would I just do createpath all over again?

btw you’re using coroutines incorrectly. The proper way is coroutine.resume(coro, ...args).

local thread = coroutine.create(function(...)
    return select("#", ...)
end)

local argCount = coroutine.resume(thread, 1, 2, 3)
print(argCount) --> 3
1 Like

No, if you just remove the local from in front of the function, you can call the function inside itself.

I am not an advanced scripter so I don’t understand what this means.

I litteraly don’t understand anything right now.

Here is the new script:

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

local path = PathfindingService:CreatePath()

function getClosestPlayer(position)
    local players = Players:GetPlayers()
    local closestDistance, closestPosition, closestPlayer = math.huge, nil, nil

    for i, player in ipairs(players) do
        if not player.Character then continue end

        local playerPosition = player.Character:GetPrimaryPartCFrame()
        local distance = (playerPosition.Position - position).Magnitude

        if distance < closestDistance then
            closestDistance = distance
            closestPosition = playerPosition.Position
            closestPlayer = player
        end
    end

    return closestPlayer, closestPosition
end

while wait(3) do
    local currentPosition = script.Parent.Torso.Position
    local closestPlayer, closestPosition = getClosestPlayer(currentPosition)
    
    path:ComputeAsync(currentPosition, closestPosition)
    if path.Status == Enum.PathStatus.Success then
        local waypoints = path:GetWaypoints()
        local currentWaypoint = 0

        path.Blocked:Connect(function(index)
            if index >= currentWaypoint then
				path:ComputeAsync(currentPosition, closestPosition)
            end
        end)
    else
		path:ComputeAsync(currentPosition, closestPosition)
    end
end

How would I change the distance?

It’s called recursion:

function thing()
    thing() --> you can call the function from inside itself
end

you have to be careful when you do it though because in the above code block it creates an infinite loop which will result in a stack overflow.

I give up on this. I don’t understand a single THING.

Oh and what’s better is I have just lost my whole script. GREAT.

Basically you want to move the code inside the while loop into a seperate function, then call that function inside the while loop.

See this is why my bio tells you more about my scripting job.

I quit making games. Thanks for helping. Bye.

Mutiple versions of your code are still posted on this thread so you can re-copy that if you want to attempt working on pathfinding again.

Sorry for wasting your o-so precious time :frowning:

Ok maybe I want to work on it again but can we do it on this post: How would I make a NPC jump when using :MoveTo() - #17 by graviiity

Since I have a new script.