Humanoid doesn't follow the waypoint, gets stuck

I have a system where a Humanoid picks 2 rooms out of 3 to visit. He calculates the path to the room. Every room has a door, which is a Part that has a PathfindingModifier inside of them (with PassThrough property set to True). If the Humanoid sees that the next waypoint label has “Door” in it’s name it runs a function called breakDoor which will make the Humanoid move infront of the door, then set the Part’s CanCollide property to False.

The Humanoid is displaying an odd behavior. Instead of following each waypoint instead it wants to go straight to the the Door, which makes it get stuck. And even when it doesn’t get there, the breakDoor function somehows runs (which means he got to the waypoint before the Door, even though he’s still stuck at a wall).

I don’t have any idea how to resolve this.

Video of the Issue: Watch Humanoid gets stuck | Streamable

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

local path = PathfindingService:CreatePath({
	AgentRadius = 2.25,
	AgentHeight = 5,
	AgentCanJump = false,
	AgentCanClimb = false,
	WaypointSpacing = 2,
})

local Intruder = workspace.Intruder
local Humanoid = Intruder.Humanoid
local HumanoidRootPart = Intruder.PrimaryPart

local roomToDoor = {
	RoomA = "DoorA",
	RoomB = "DoorB",
	RoomC = "DoorC",
}

local function breakDoor(room: string)
	local Door = workspace[roomToDoor[room]]
	
	if not Door:GetAttribute("open") then
		Humanoid:MoveTo(Door.Attachment.WorldPosition)
		Humanoid.MoveToFinished:Wait()
	
		print("Breaking door...")
		
		TweenService:Create(HumanoidRootPart, TweenInfo.new(1, Enum.EasingStyle.Quint), {
			CFrame = CFrame.lookAt(HumanoidRootPart.Position, Vector3.new(Door.Position.X, HumanoidRootPart.Position.Y, Door.Position.Z)),
		}):Play()
		
		task.wait(5)
		
		print("Door broken")
		Door.CanCollide = false
		Door:SetAttribute("open", true)
	end
end

local function walkPath(target: BasePart)
	local success, err = pcall(function()
		path:ComputeAsync(HumanoidRootPart.Position, target.Position)
	end)
	
	if success and path.Status == Enum.PathStatus.Success then
		local Waypoints = path:GetWaypoints()
		table.remove(Waypoints, 1)
		
		local nextWaypointIndex = 1
		local pathBlockedConnection
			
		pathBlockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
			if blockedWaypointIndex >= nextWaypointIndex then
				pathBlockedConnection:Disconnect()
				walkPath(target)
			end
		end)
		
		local dots = {}
		
		task.spawn(function()
			for _, waypoint in Waypoints do
				local Part = Instance.new("Part")
				Part.Shape = Enum.PartType.Ball
				Part.Size = Vector3.new(0.5,0.5,0.5)
				Part.Anchored = true
				Part.CanCollide = false
				Part.Material = Enum.Material.Neon
				Part.Parent = workspace
				Part.CFrame = CFrame.new(waypoint.Position)
				
				table.insert(dots, Part)
			end
		end)
		
		for index, waypoint in Waypoints do -- Iterate through the waypoints
			local success = false
			
			repeat
				print(waypoint.Label)
				Humanoid:MoveTo(waypoint.Position)
				
				success = Humanoid.MoveToFinished:Wait() -- Wait until the Humanoid has reached the waypoint
			until success
			
			nextWaypointIndex = index + 1

			if nextWaypointIndex < #Waypoints then -- If the Humanoid has reached and it isn't the last waypoint
				if string.find(Waypoints[nextWaypointIndex].Label, "Door") then
					breakDoor(target.Name)
				end
			else
				pathBlockedConnection:Disconnect()
			end
		end
		
		print("Finished walking to target")
		
		task.spawn(function()
			for _, waypoint in dots do
				waypoint:Destroy()
			end
		end)
	end
end

function main()
	local rooms = {}
	
	for roomName, _ in roomToDoor do
		table.insert(rooms, roomName)
	end
	
	for i=1,2 do
		local index = math.random(1, #rooms)
		local randomRoom = table.remove(rooms, index)
		
		local Room = workspace[randomRoom]
		print(Room)
		walkPath(Room)
		
		task.wait(5)
	end
end

task.wait(10)

main()
1 Like

MoveToFinished event is kind of weird.
You should probably look for alternatives/handle timeout for this event
If you want pathfinding to ignore object you can add PathfindingModifier | Documentation - Roblox Creator Hub inside that object althrough make sure your path object has its label having the cheapest path value

if you want to handle timeout you can use
task library + coroutines:

local thread:Thread = coroutine.running()

etc