Strange behaviour from subsequent Path:ComputeAsync() calls

I’m making a Pathfinding module to help break up larger amounts of Pathfinding calls, letting my NPCs call them without chugging up the game too much.

However, I’m noticing something a little weird when calling new ComputeAsync on an old Path object with new parameters. Everytime I “refresh” the path, I call ComputeAsync again and if it’s succesful I connect a Blocked event. With our starting Start and Destination variables, this will always print once when blocked.

But if I ever call ComputeAsync on the path again, this time with new variables, the Blocked event will trigger again for every time I’ve called ComputeAsync with unique variables.

I’m not entirely sure whats going on here to be perfectly honest. Here is the code I’m using;

Pathfinding Module;
local PFS = game:GetService("PathfindingService")

local Pathfinder = {}

local Agent = {}
local Agent_mt = {__index = Agent}

function Agent.Create()
	local self = {}
	self.Path = PFS:CreatePath()
	self.Status = nil;
	self.WayPoints = {};
	self.Visuals = {};
	self.BlockedConnection = nil;
	
	return setmetatable(self, Agent_mt)
end

function Agent:NewPath(Start, Destination)
	if Start == nil or Destination == nil then
		error("Invalid Path locations passed")
	end
	self.Start = Start
	self.Destination = Destination
	self.WayPoints = {}
	Pathfinder.PathingQueue[self] = self
end

function Agent:CalcPath()
	self.Path:ComputeAsync(self.Start, self.Destination)
	if self.Path.Status == Enum.PathStatus.Success then
		self.WayPoints = self.Path:GetWaypoints()
		self.BlockedConnection = self.Path.Blocked:Connect(function(WPI)
			self.BlockedConnection:Disconnect()
			self:PathIsBlocked(WPI)
		end)
	end
end

function Agent:CancelPath()
	if Pathfinder.PathingQueue[self] then
		table.remove(Pathfinder.PathingQueue, self)
	end
end

function Agent:PathIsBlocked(BlockedIndex)
	print("Path is Blocked at", BlockedIndex)
	Pathfinder.PathingQueue[self] = self
	--Our path has become blocked. 
	--Try again.
	--This will eventually have a failure cap.
end

function Agent:PathFailure()
	--Our path cannot be made
end

Pathfinder.PathingQueue = {}
--We add Agents to our pathing queue and iterate through them per-frame.
function Pathfinder.Create()
	return Agent.Create()
end

function Pathfinder:Update()
	local int = 0
	for Ref, Agent in pairs(Pathfinder.PathingQueue) do
		int = int + 1
		print(int)
		Pathfinder.PathingQueue[Ref] = nil
		Agent:CalcPath()
	end
end
--Currently this will iterate through everything in the PathfindingQueue every frame.
--We remove the Agent every time its called, and eventually we will create a CalcPath cap here.

return Pathfinder
Activation
local Path = require(PATH TO PATHFINDING MODULE HERE); 
		local NA = Path.Create() 
function MakePath (actionName, userInputState, input)
		NA:NewPath(workspace:WaitForChild("GroupSwitch").Position, workspace:WaitForChild("NPC1").Position)
end

Again, when the start and destination variables are the same, the “Path is blocked” will only print once. But for every time the variables change, it will print again.

1 Like

I have ran into a similar issue in the past where my connections had been yielding onto each other. The solution to that was having to make another ModuleScript which serves the purpose of disconnecting previous connections and perhaps that can be something you may want to look into.

This is what had happened to me; perhaps you may want to check it out:

2 Likes

Aha! While not being the direct solution, you did get me to realise that I never disconnect in the NewPath call, only if its current instance is blocked.
Though why that would stack in the way it did is a little beyond me.
Thank you!

1 Like