Monster PathFinding Issues

I recently made a monster script that uses moveto that follow pathfinding waypoints to follow nodes, when a players close enough it ditches that node and chases player, but it does it so badly i dont know how to ix it, it either doesnt move in normal and moves in chase or moves in nodes but not chase

Hello,
You could make a variable for when the monster is chasing or in roaming mode, and when following the nodes, check if it’s in a chase or not, and if it is, break out of the loop.

Here’s an exemple:

local Humanoid = Monster.Humanoid
local Waypoints = Path:GetWaypoints() --You should have that part already.
local Chase = false

for i,v in Waypoints do
   if Chase == false then
      Humanoid:MoveTo(v.Position)
      Humanoid.MoveToFinished:Wait()
   else
      break
   end
end
1 Like

My script already has these, i even asked gpt, noone to come

Hello? I’ve been waiting so long for someone that wont even arrive.

1 Like

i arrived but i dont understand whats the problem, can you explain more specifically?

No video, No script:
How are we supposed to help?

1 Like
local npc = script.Parent
local humanoid = npc:FindFirstChildOfClass("Humanoid")
local rootPart = npc:FindFirstChild("HumanoidRootPart")
local nodesFolder = workspace:FindFirstChild("Noces")
local players = game:GetService("Players")
local pathfindingService = game:GetService("PathfindingService")

local roamDelay = 0.2
local detectionRange = 135
local nodeBlacklist = {}
local currentWaypoints = {}
local currentWaypointIndex = 1
local isFollowingWaypoints = false

local walkAnimation = Instance.new("Animation")
walkAnimation.AnimationId = "rbxassetid://72349975684395"
local runAnimation = Instance.new("Animation")
runAnimation.AnimationId = "rbxassetid://128376275068977"

local walkTrack = humanoid:LoadAnimation(walkAnimation)
local runTrack = humanoid:LoadAnimation(runAnimation)

local alertSound = Instance.new("Sound", rootPart)
alertSound.SoundId = "rbxassetid://9069546509"
alertSound.Volume = 1

local chaseSound = Instance.new("Sound", rootPart)
chaseSound.SoundId = "rbxassetid://118938971925008"
chaseSound.Volume = 6
chaseSound.PlaybackSpeed = 0.8
chaseSound.Looped = true

humanoid.WalkSpeed = 16

local function clearWaypoints()
    currentWaypoints = {}
    currentWaypointIndex = 1
    isFollowingWaypoints = false
end

local function getNearestPlayer()
    local nearestPlayer, nearestDistance = nil, detectionRange
    for _, player in pairs(players:GetPlayers()) do
        if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
            local distance = (player.Character.HumanoidRootPart.Position - rootPart.Position).Magnitude
            if distance < nearestDistance then
                nearestDistance = distance
                nearestPlayer = player
            end
        end
    end
    return nearestPlayer
end

local function getClosestNode()
    local closestNode, closestDistance = nil, math.huge
    local farNodes = {}
    if nodesFolder then
        for _, node in pairs(nodesFolder:GetChildren()) do
            if node:IsA("BasePart") and not nodeBlacklist[node] then
                local distance = (node.Position - rootPart.Position).Magnitude
                if distance < closestDistance then
                    closestDistance = distance
                    closestNode = node
                end
                table.insert(farNodes, node)
            end
        end
    end
    if not closestNode and #farNodes > 0 then
        closestNode = farNodes[math.random(1, #farNodes)]
    end
    return closestNode
end

local function blacklistNode(node)
    nodeBlacklist[node] = true
    task.delay(7, function()
        nodeBlacklist[node] = nil
    end)
end

local function handleObstacle()
    if humanoid:GetState() == Enum.HumanoidStateType.Seated then return end
    humanoid.Jump = true
end

local function onTouch(hit)
    local player = players:GetPlayerFromCharacter(hit.Parent)
    if player then
        player:Kick("foolish")
    end
end

rootPart.Touched:Connect(onTouch)

local function calculatePathTo(targetPosition)
    local path = pathfindingService:CreatePath({
        AgentRadius = 2,
        AgentHeight = 5,
        AgentCanJump = true,
        AgentCanClimb = true
    })
    
    path:ComputeAsync(rootPart.Position, targetPosition)
    
    if path.Status == Enum.PathStatus.Success then
        local waypoints = path:GetWaypoints()
        if #waypoints > 0 then
            return waypoints
        end
    end
    
    return nil
end

local function moveToNextWaypoint()
    if not isFollowingWaypoints or #currentWaypoints == 0 then return end
    
    if currentWaypointIndex > #currentWaypoints then
        clearWaypoints()
        return true
    end
    
    local waypoint = currentWaypoints[currentWaypointIndex]
    
    humanoid:MoveTo(waypoint.Position)
    
    local distanceToWaypoint = (waypoint.Position - rootPart.Position).Magnitude
    
    if distanceToWaypoint < 3 then
        currentWaypointIndex = currentWaypointIndex + 1
        
        if waypoint.Action == Enum.PathWaypointAction.Jump then
            humanoid.Jump = true
        end
    end
    
    return false
end

local function followWaypoints()
    isFollowingWaypoints = true
    
    while isFollowingWaypoints and #currentWaypoints > 0 do
        local reachedEnd = moveToNextWaypoint()
        if reachedEnd then
            break
        end
        task.wait(roamDelay)
    end
    
    isFollowingWaypoints = false
end

local function roam()
    humanoid.WalkSpeed = 15
    if chaseSound.IsPlaying then
        chaseSound:Stop()
    end
    if alertSound.IsPlaying then
        alertSound:Stop()
    end

    while true do
        local player = getNearestPlayer()
        if player then 
            clearWaypoints()
            return 
        end

        local node = getClosestNode()
        if node then
            local waypoints = calculatePathTo(node.Position)
            
            if waypoints then
                currentWaypoints = waypoints
                currentWaypointIndex = 1
                
                if not walkTrack.IsPlaying then 
                    walkTrack:Play() 
                end
                
                followWaypoints()
                
                if currentWaypointIndex > #currentWaypoints then
                    blacklistNode(node)
                end
            else
                humanoid:MoveTo(node.Position)
                humanoid.MoveToFinished:Wait()
                blacklistNode(node)
            end
        end
        
        task.wait(0.5)
    end
end

local function chase(player)
    humanoid.WalkSpeed = 20
    if not alertSound.IsPlaying then
        alertSound:Play()
    end
    if not chaseSound.IsPlaying then
        chaseSound:Play()
    end
    
    clearWaypoints()

    while player do
        local character = player.Character
        if character and character:FindFirstChild("HumanoidRootPart") then
            local targetPosition = character.HumanoidRootPart.Position
            local distance = (targetPosition - rootPart.Position).Magnitude
            
            if distance > detectionRange then 
                chaseSound:Stop() 
                alertSound:Stop()
                clearWaypoints()
                return 
            end

            local waypoints = calculatePathTo(targetPosition)
            
            if waypoints then
                currentWaypoints = waypoints
                currentWaypointIndex = 1
                
                if not runTrack.IsPlaying then
                    walkTrack:Stop()
                    runTrack:Play()
                end
                
                moveToNextWaypoint()
            else
                humanoid:MoveTo(targetPosition)
            end
        else
            break
        end
        
        task.wait(roamDelay)
    end
    
    clearWaypoints()
end

while true do
    local player = getNearestPlayer()
    if player then
        chase(player)
    else
        if not walkTrack.IsPlaying then
            runTrack:Stop()
            walkTrack:Play()
        end
        roam()
    end
    task.wait(0.5)
end

If someones there, please help me

Hello!
After looking through your script a bit, and a bit of testing, I may have found a problem.

In your calculatePathTo function, you determine whether your monster should chase or follow the player by checking if there are any waypoints with this if statement: if #waypoints > 0 then. But I did some testing in studio, and saw that there is always a waypoint at the start position, and the end position, which means there will always be a minimum of 2 waypoints, which in result, means that that if statement will never be false. To fix this just replace the 0 with a 2, and hopefully that should fix it.

Also, you can set it to 3 since the start and end positions have to be very close for only 2 waypoints to generate.

If this doesn’t fix your problem, could you provide a video of the problem, and maybe a more in depth explanation, since the one in the original post was a bit hard to follow.

I hope this helps!