This is a problem ive had for YEARS. i remember trying to do this most recently about 3 years ago. didnt work then, doesnt work now. no matter how i code it, no matter how clean it is, i always test everything i think of. And its always the pathfinding service. Introducing the pathfinding service always causes a problem. this is a HuGE deal for me.
-
What do you want to achieve? Keep it simple and clear!
I want to create a simple npc that follows the player (in my case its hardcoded to my character, “AlexanderYar”) using roblox pathfinding. -
What is the issue? Include screenshots / videos if possible!
after about 2 minutes or so, the npc starts to gradually fail to move to the next waypoint. and ive tested it, it knows the next waypoint. its :MoveTo that fails to work. But I dont think the problem is :moveto in itself because i testing the same npc with pathfinding removed and instead doing a bunch of random positions. It works fine. But introducing roblox pathfinding breaks it for some reason. -
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
oh ive tried it all. i tested all i can think of. Recently i had the idea it might be a memory leak. but memory seems fine. AND GUESS WHAT. today i tried again but i made a strange discovery. creating a bunch of parts seems to fix the npc and it moves freely again, without stopping, temporarily.
Here are two posts ive read.
post 1
post 2
And this recently lead me to believing it was a memory leak, especially since in post 1, someone said the problem was fixed, and that was posted in May 2023. And post 2, which is a similar issue, was posted in OCTOBER 2023, after it was said to be fixed. So i thought maybe the devs skipped something and theres still a memory leakage. But i did more testing and it doesnt seem like a memory leakage.
the game is an empty baseplate with
- some obstacles
- the npc with the script in it
- the clickable part which spawns in 100 little balls above it
- christmas tree
i verified these are the only two scripts. i ran this and it says “t(x2)”
the script in the npc and the script in the clickable part. So nothing else can be interfering that i added.
for i,v in pairs(game.Workspace:GetDescendants()) do if v:IsA("Script") then print"t" end end
this is the script in the npc.
If you are too lazy or confused, ill explain it. There are two parts to it. One part sets new waypoints every 5 seconds (made it 5 seconds whilst debugging because i wanted to make sure the problem wasnt that i was updating the waypoints too fast.), the next part constantly goes to the next waypoint.
The first part does its job by waiting 5 seconds, then computingAsync the path and sets the global variable “waypooints” to the path’s waypoints, then it updates the serial variable, then it shows a visualization of the waypoints.
the point of the serial variable is to check when the waypoints variable is updated.
the second part works by using an index which decides which waypoint in the current waypoints variable it should be walking towards. I did this because if i just made it always go to waypoints[2] (which is the first waypoint that matters), then it would get stuck at that waypoint until the path was computed again.
every time a waypoint is reached, i increment the index and it goes to the next one.
Every .Stepped, it checks the serial, if its different, then it simply changes the index back to 2 so that it starts from the beginning of the new waypoints path.
Also, it constantly prints the distance from npc to the current waypoint.
local SRVC_pathdinder = game:GetService("PathfindingService")
local SRVC_runservice = game:GetService("RunService")
local SRVC_memoryservice = game:GetService("MemoryStoreService")
local targetPlr:Player = game.Players:WaitForChild("AlexanderYar")
local targetChar = targetPlr.Character
if targetChar == nil then
targetPlr.CharacterAppearanceLoaded:Wait()
targetChar = targetPlr.Character
end
local targetHRP:BasePart = targetChar:WaitForChild("HumanoidRootPart")
local hum:Humanoid = script.Parent:WaitForChild("Humanoid")
local hrp:BasePart = script.Parent:WaitForChild("HumanoidRootPart")
wait()
local pathParams = {
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentCanClimb = true,
WaypointSpacing = math.huge,
Costs = {}
}
local path:Path = SRVC_pathdinder:CreatePath()
local waypoints
local serial = 1 -- used to tell if waypoints was updated.
local calculateWaypointsCooldown = 5
coroutine.wrap(function() -- calculate new waypoints
while true do
wait(calculateWaypointsCooldown)
local success, errorMessage = pcall(function()
path:ComputeAsync(hrp.Position, targetHRP.Position)
end)
if success then
waypoints = path:GetWaypoints()
serial = serial +1
if serial >= 1023 then
serial = 0
end
for i,v:PathWaypoint in pairs(path:GetWaypoints()) do -- DEBUG START
local part = Instance.new("Part")
part.Anchored = true
part.Shape = Enum.PartType.Ball
part.Size = Vector3.new(1, 1, 1)
part.Color = Color3.fromRGB(255, 0, 0)
part.Material = Enum.Material.Neon
part.Position = v.Position
part.CanCollide = false
part.Parent = game.Workspace
coroutine.wrap(function()
wait(calculateWaypointsCooldown)
part:Destroy()
end)()
end -- DEBUG END
else
warn("Path not computed!", errorMessage)
end
end
end)()
local lastSerial = 0
local gotoIndex = 2 -- index in waypoints to go to. this makes sure that it keeps following the path even if waypoints hasnt been updated. it wont get stuck at waypoint[2] anymore
local distanceVector3:Vector3 = Vector3.zero -- distance between hrp and current waypoint
local distance:number = 0
SRVC_runservice.Stepped:Connect(function() -- move the npc
if lastSerial ~= serial then
gotoIndex = 2
lastSerial = serial
end
if (waypoints ~= nil and waypoints[gotoIndex] ~= nil) then
distanceVector3 = waypoints[gotoIndex].Position -hrp.Position
distance = Vector3.new(distanceVector3.X, 0, distanceVector3.Z).magnitude
print(distance) -- TODO. IM PRETTY SURE PATHFINDING SERVICE HAS A MEMORY LEAK. CHECK DEV CONSOLE AND PLAY THE GAME FOR ABOUT 2 MINS. YOULL SEE IT KEEPS GOING UP AND IT SLOWS DOWN. MY CODE IS FINE, THE PROBLEM IS THE SERVER IS DYING.
--print(distance) -- DEBUG
if distance <= .5 then -- checks for if hum reached waypoint, if so, move on to next one unless there isnt a next one.
if (waypoints[gotoIndex +1] ~= nil) then -- checks if next waypoint exists
gotoIndex = gotoIndex +1
end
end
hum:MoveTo(waypoints[gotoIndex].Position)
--print(waypoints[gotoIndex].Action == Enum.PathWaypointAction.Jump) -- DEBUG
if (waypoints[gotoIndex].Action == Enum.PathWaypointAction.Jump and hum:GetState() ~= Enum.HumanoidStateType.Jumping and hum:GetState() ~= Enum.HumanoidStateType.Freefall) then -- if jumping is necessary, jump UNLESS the hum is already jumping
hum.Jump = true
end
end
end)
this is the script inside the clickable part
script.Parent.ClickDetector.MouseClick:Connect(function()
for i = 1, 100, 1 do
local part = Instance.new("Part")
part.Anchored = false
part.Shape = Enum.PartType.Ball
part.Size = Vector3.new(1, 1, 1)
part.Color = Color3.fromRGB(0, 255, 255)
part.Material = Enum.Material.Neon
part.Position = script.Parent.Position +Vector3.new(0, 2, 0)
part.CanCollide = true
part.Parent = game.Workspace
end
end)
heres a video demonstration (low fps sorry, but i promise it looks smooth at first). Notice
- it works as intended (except jumping but ill deal with that later) it moves around obstacles fine
- after about 2 mins, it starts to get stuck sooner and sooner, eventually only moving to the first waypoint every time the path is updated
- the printed value (which is distance to current waypoint) is more then .5, meaning nothing changed, waypoints are the same and serial is the same, and it SHOULD keep moving, but it simple stops and fails to move further.
- the memory seems to be fine
- the npc at first moves the same speed as me, meaning it works as it should until the thing starts happening
- the npc does the same thing in server view, so its not a network stuttering issue that im concerned about.
- clicking the part and adding all those little balls temporarily fixes the npc, then it goes back to doing the same thing again.
demonstration video
I dont care what the solution is… if there is one. Ive been using roblox for a long time. And if theres one thing I could never do, its this. And I dont care if its a simple solution and ive been a bozo for 6 years. I want to figure this out already. I mean just LOOK at it. its a small script (my style uses a lot of spacing so it looks big, sorry) and ignoring the checks and the visualization, whats left is simply it calculating new waypoints every 5 seconds, and constantly moving the npc to the next waypoint, making sure to restart when the waypoints update. thats IT.
id appreciate comments, solutions, suggestions and such. <3