Pathfinding NPC weird stepping movement when AI is moved off original path

So I have been trying to make my own Pathfinding AI, and all has been going pretty well so far. All though there’s is this one problem that causes issues, and that’s when ever the AI has been moved back or off the original path a bit, the AI seems to walk in like a weird stepping motion, as seen below:

There’s also another problem which is the path.Blocked() function firing constantly around at line 81. Despite the path either being blocked or not

Some solutions I have already tried is putting the FollowPath() function in a loop, but that seems to cause even more issues (with things such as the AI running in circles and/or jumping and moving very incorrectly)

local PathfindingService = game:GetService("PathfindingService")

local NPC = script.Parent
local NPCHumanoid = NPC:WaitForChild("Humanoid")

local Path = PathfindingService:CreatePath({
	AgentRadius = 3,
	AgentHeight = 6,
	AgentCanJump = true,
	WaypointSpacing = 3,
	Costs = { -- Prefered Paths (The higher the value, the less likely the AI will use it) (set to math.huge to avoid it completely
		Water = 10,
		Mud = 20,
		DangerZone = math.huge,
	}
})

local Waypoints
local NextWaypointIndex
local ReachedConnection
local BlockedConnection

local function CreateDebugPart(Position, Colour)
	local DebugPart = Instance.new("Part")
	DebugPart.Anchored = true
	DebugPart.CanCollide = false
	DebugPart.CanQuery = false
	DebugPart.Transparency = 0.5
	DebugPart.Shape = Enum.PartType.Ball
	DebugPart.Color = Colour
	DebugPart.Size = Vector3.new(1, 1, 1)
	DebugPart.Position = Position
	DebugPart.Name = "DebugPart"
	DebugPart.Parent = workspace

	return DebugPart
end

-- Visualize the path
local function CreateDebugPathParts()
	local DebugWaypoints = Path:GetWaypoints()

	local function CreateWaypointPartsFolder()
		local Folder = Instance.new("Folder")
		Folder.Name = "WaypointParts"
		Folder.Parent = workspace
		return Folder
	end

	local WaypointsFolder = workspace:FindFirstChild("WaypointParts") or CreateWaypointPartsFolder()

	for i, WaypointPart in ipairs(WaypointsFolder:GetChildren()) do
		WaypointPart:Destroy()
	end

	for i, Waypoint in ipairs(DebugWaypoints) do
		local Part
		if Waypoint.Action == Enum.PathWaypointAction.Walk then
			Part = CreateDebugPart(Waypoint.Position, Color3.fromRGB(34, 255, 11))
		else
			Part = CreateDebugPart(Waypoint.Position, Color3.fromRGB(0, 0, 248))
		end

		Part.Parent = WaypointsFolder
	end
end

local function FollowPath(Destination)
	-- Compute the path
	local Success, ErrorMessage = pcall(function()
		Path:ComputeAsync(NPC.PrimaryPart.Position, Destination)
	end)

	CreateDebugPathParts()

	if Success and Path.Status == Enum.PathStatus.Success then -- The AI can use this path/destion!
		-- Get the path waypoints
		Waypoints = Path:GetWaypoints()

		-- Detect if path becomes blocked
		BlockedConnection = Path.Blocked:Connect(function(BlockedWaypointIndex)
			print("Blocked")
			-- Check if the obstacle is further down the path
			if BlockedWaypointIndex >= NextWaypointIndex then
				-- Stop detecting path blockage until path is re-computed
				BlockedConnection:Disconnect()
				-- Call function to re-compute new path
				FollowPath(Destination)
			end
		end)

		-- Detect when movement to next waypoint is complete
		if not ReachedConnection then
			ReachedConnection = NPCHumanoid.MoveToFinished:Connect(function(Reached)
				if Reached and NextWaypointIndex < #Waypoints then
					-- Increase waypoint index and move to next waypoint
					NextWaypointIndex += 1
					NPCHumanoid:MoveTo(Waypoints[NextWaypointIndex].Position)
					
					if Waypoints[NextWaypointIndex].Action == Enum.PathWaypointAction.Jump then
						NPCHumanoid.Jump = true
					end
				elseif Reached then
					ReachedConnection:Disconnect()
					BlockedConnection:Disconnect()
					print("Destination reached!")
				else
					ReachedConnection:Disconnect()
					BlockedConnection:Disconnect()
					FollowPath(Destination)
				end
			end)
		end

		-- Initially move to second waypoint (first waypoint is path start; skip it)
		NextWaypointIndex = 2
		NPCHumanoid:MoveTo(Waypoints[NextWaypointIndex].Position)
		
	else
		warn("Path not computed!", ErrorMessage)
		FollowPath(Destination)
	end
end

--while true do
	FollowPath(workspace.DestinationPart.Position)
	--wait()
--end
2 Likes

don’t make a loop calling the function OUTSIDE, do it from inside the function

here’s what i did:

local function FollowPath(Destination)
	-- Compute the path
	local Success, ErrorMessage = pcall(function()
		Path:ComputeAsync(NPC.Torso.Position, Destination)
	end)
	
	CreateDebugPathParts()

	if Success and Path.Status == Enum.PathStatus.Success then -- The AI can use this path/destination!
		-- Get the path waypoints
		Waypoints = Path:GetWaypoints()

		-- Detect if path becomes blocked
		BlockedConnection = Path.Blocked:Connect(function(BlockedWaypointIndex)
			print("Blocked")
			-- Check if the obstacle is further down the path
			if BlockedWaypointIndex >= NextWaypointIndex then
				-- Stop detecting path blockage until path is re-computed
				BlockedConnection:Disconnect()
				-- Call function to re-compute new path
				FollowPath(Destination)
			end
		end)
		
		NextWaypointIndex = 2
		
		-- Detect when movement to next waypoint is complete
		
		while anti == true and wait(0.5) do
			if NextWaypointIndex < #Waypoints and (NPC.Torso.Position - Destination).Magnitude > 10 then
				-- Increase waypoint index and move to next waypoint
				NextWaypointIndex += 1
				NPCHumanoid:MoveTo(Waypoints[NextWaypointIndex].Position)

				if Waypoints[NextWaypointIndex].Action == Enum.PathWaypointAction.Jump then
					NPCHumanoid.Jump = true
				end
			elseif (NPC.Torso.Position - Destination).Magnitude <= 10 then
				BlockedConnection:Disconnect()
				anti = false
				print("Destination reached!")
			else
				BlockedConnection:Disconnect()
				FollowPath(Destination)
			end

			--Initially move to second waypoint (first waypoint is path start; skip it)
			
			NPCHumanoid:MoveTo(Waypoints[NextWaypointIndex].Position)
		end
	else
		FollowPath(Destination)
	end
end

not sure it’ll solve the characters stepping though, i gave the parameters a waypointspacing of 12

1 Like