Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Why does my pathfinding npc keeps staggering?

Asked by 3 years ago

I'm making an office with NPC employees that walk around. They go from stations, meetings, to the break room, and etc.

When the npc's are first spawned they walk perfectly fine to their next station, but after a set amount of time when they go to their next, they walk super slow and jolty. Very similarly to the NPC in this video: https://i.gyazo.com/4571575e0383753710c1b35ec7bd2df7.mp4

here's the code (all of my npc scripts are regular scripts & not local btw)

local PathfindingService = game:GetService("PathfindingService")
local char = script.Parent.Parent
local RepStorage = game:GetService("ReplicatedStorage")
local hrp = char.HumanoidRootPart

if hrp:CanSetNetworkOwnership() then
    hrp:SetNetworkOwner(nil) -- setting the owner to the server
end

local function GoToNexStation ()
    wait()
    local destination1 = game.Workspace[char.PathFinding.NexStation.Value]
    local destination = Vector3.new((destination1.Position.X), (hrp.Position.Y), (destination1.Position.Z))
    local waypoints = {}
    local currentWaypointIndex = 0
    local agentParams = {
        ["AgentHeight"] = 5,
        ["AgentRadius"] = 2,
        ["AgentCanJump"] = true,
        ["WayPointSpacing"] = 4
    }

    local path = PathfindingService:CreatePath(agentParams)

    local function followPath()
        path:ComputeAsync(hrp.Position, destination)
        waypoints = {}

        if path.Status == Enum.PathStatus.Success then
            waypoints = path:GetWaypoints() 
            currentWaypointIndex = 1
            for i, waypoint in pairs(waypoints) do
                if char.Name == "Gale" then
                    print(currentWaypointIndex, " / ", #waypoints)
                end
                if waypoints[currentWaypointIndex] ~= nil then
                    if currentWaypointIndex <= #waypoints then
                        if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
                            char.Humanoid.Jump = true
                        end
                        local evt = Instance.new("BindableEvent")
                        delay(2, function() 
                            if evt then 
                                evt:Fire("Timeout") 
                            end 
                        end)
                        char.Humanoid.MoveToFinished:Connect(function() if evt then evt:Fire("Finished") end end)

                        if currentWaypointIndex <= #waypoints then
                            char.Humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
                        end

                        local result = evt.Event:Wait()
                        evt:Destroy()
                        evt = nil
                        if result == "Timeout" then
                            char.Humanoid.Jump = true
                            currentWaypointIndex = #waypoints + 1 -- cancel out
                            GoToNexStation ()
                            return {status = 0}
                        end



                        if currentWaypointIndex == #waypoints then
                            char.HumanoidRootPart.CFrame = CFrame.new(destination1.Position) * CFrame.Angles(math.rad(destination1.Orientation.X), math.rad(destination1.Orientation.Y), math.rad(destination1.Orientation.Z))
                            char.PathFinding.CurStation.Value = char.PathFinding.NexStation.Value
                        end
                        currentWaypointIndex = currentWaypointIndex + 1
                    end
                end
            end
            return {status = 1}
        else
            if char.PathFinding.CurStation.Value ~= char.PathFinding.NexStation.Value then
                print("failure")
                currentWaypointIndex = #waypoints + 1 -- cancel out
                GoToNexStation ()
            end
        end
    end

local function onPathBlocked(blockedWaypointIndex)
        print("Blocked")
            currentWaypointIndex = #waypoints + 1 -- cancel out
        GoToNexStation ()
        return
    end

From what I've read people have all said its either from spamming :MoveTo in a loop or from Network Ownership

I do have it print each time the player walks to a station or starts a new path, so I'm 99% positive it has nothing to do with spamming :MoveTo. I also implemented a bunch of returns and ways to stop the script from spamming it.

I've tried setting the network owner in the script I use to spawn them (separate script from above) where I used this code:

local npc = game.Workspace:FindFirstChild("Noob"):Clone()
local function setNetworkOwnerOfModel(model, networkOwner)
            for _, descendant in pairs(model:GetDescendants()) do
                -- Go through each part of the model
                if descendant:IsA("BasePart") then
                    -- Try to set the network owner
                    local success, errorReason = descendant:CanSetNetworkOwnership()
                    if success then
                        descendant:SetNetworkOwner(networkOwner)
                    else
                        -- Sometimes this can fail, so throw an error to prevent
                        -- ... mixed networkownership in the 'model'
                        error(errorReason)
                    end
                end
            end
        end
        setNetworkOwnerOfModel(npc, nil)

The odd thing is that it sometimes happens & sometimes doesn't. Although it usually does. I believe it could have something to do with the "blocked" function, or the else statement I put for if the path:ComputeAsync doesn't == success. But I could be wrong and it could be something else. I'm genuinely so confused.

There's a lot of different articles on "NPC pathfinding staggering" but I just can't seem to find a solution that works for me.

I've looked at every article I can find on it on scriptinghelpers and devforum and I just can't seem to fix anything.

Answer this question