NPCs going back and forth if given a new path before completing their current

I’m helping make a prison game that will have NPCs with schedules, I have a script updating the time and firing events at times when all NPCs should move. If an NPC has not made it to their goal before the next event is fired, they should cancel their route and begin pathfinding to the next point.

All NPCs have their own places they need to be at certain times and their schedules are attributes on their models.

Currently, if an NPC is unable to make it to their current destination before the next, instead of cancelling their current path, they go back and forth and eventually the paths seem to stack up and they go insane and run into walls.

If NPCs are able to make it to all their goals on time the script runs fine.

I’ve read through other posts on the forum talking about this issue. One suggested adding a thread check, using newproxy(). Another suggested a path cancel function to be called whenever the schedule event is fired. Neither of these methods worked for me.

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

local function pathFindTo(char, destination)
	local path = PathfindingService:ComputeRawPathAsync(char.HumanoidRootPart.Position, destination.Entrance.Position, math.huge)

	local waypoints = path:GetWaypoints()

	for i, waypoint in ipairs(path:GetWaypoints()) do
		if waypoints[i].Action == Enum.PathWaypointAction.Jump then
			char:FindFirstChildWhichIsA("Humanoid").Jump = true
		end

		char:FindFirstChildWhichIsA("Humanoid"):MoveTo(waypoints[i].Position)
		char:FindFirstChildWhichIsA("Humanoid").MoveToFinished:Wait()
	end
end


for i, char in ipairs(workspace.Characters:GetChildren()) do
	char.PrimaryPart:SetNetworkOwner(nil)

	ReplicatedStorage.Events.UpdateSchedule.Event:Connect(function(eventTime)
		if char:GetAttribute("At"..eventTime) == nil then return end
		local destination = workspace.Prison:FindFirstChild(char:GetAttribute("At"..eventTime))
		pathFindTo(char, destination)
	end)
end


Being printed is the minutes after midnight - the intended path of the NPCs is to go back around the corner they came from.

Also let me know if I need to clean up my script or if I messed up anything stupid I’m new to scripting!!

1 Like

You can use some value that, if changed, will stop the old path following. For example, every time a npc starts following waypoints, set an attribute for character, like “CurrentTarget”, and after each passed waypoint check if the value of this attribute is equal to the target that is set for this path. Like this:

local currentTarget = destination.Entrance.Position -- Set target point of THIS path follow
char:SetAttribute('CurrentTarget', currentTarget) -- Setting the attribute

for i, waypoint in ipairs(path:GetWaypoints()) do
	-- stuff

    local actualTarget = char:GetAttribute('CurrentTarget') -- Getting last updated target
    if actualTarget ~= currentTarget then return end
end

Also i would replace .MoveToFinished:Wait() to a loop that checks the distance to the waypoint few times a second and if it is small, the npc will start walking to the next waypoint. This way you can check for target change more often and get rid of possible delays between movements.

while task.wait(0.1) do
    local distance = (char.PrimaryPart.Position - waypoints[i].Position).Magnitude
    if distance < 2 or char:GetAttribute('CurrentTarget') ~= currentTarget then 
        break 
    end
end
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.