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 return
s 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.