Detecting if ControllerManager has reached certain position (or basically a waypoint)

Hi!
I was trying to create AI NPC with new ControllerManagers. Everything works fine, NPC is moving but I encountered a serious problem. I have no idea how would I detect if NPC reached a certain position (or basically a waypoint that PathfindingService generates for example). Kinda like (Humanoid :: Humanoid).MoveToFinished event. I tried many solutions and pretty much all of them seem too unreliable. I tried checking Magnitude between NPC and position every frame, calculating time to yield from v=s/t formula. Basically everything. Unfortunately every option is unreliable. So my main question is, has anyone ever used ControllerManagers to control NPCs rather than player’s character and knows how to do that properly?

I really appreciate your help.

I’ve been working with ControllerManager too, and I totally get your frustration — it doesn’t have a built-in .MoveToFinished event like Humanoid:MoveTo(), so detecting arrival isn’t as straightforward.

But don’t worry! Here are a few solid strategies that can help make this more reliable:

  1. Use a Region-Based Arrival Check (Better Than Magnitude)

Instead of checking raw .Magnitude every frame (which can be noisy due to slight model jitters), try defining a small radius or region and check if the NPC’s HumanoidRootPart is within that area.

Here’s a simple example:

local ARRIVAL_RADIUS = 2

function hasReachedPosition(npc, targetPosition)
	local root = npc:FindFirstChild("HumanoidRootPart")
	if root then
		local horizontalDist = (Vector3.new(targetPosition.X, 0, targetPosition.Z) - Vector3.new(root.Position.X, 0, root.Position.Z)).Magnitude
		local verticalDist = math.abs(targetPosition.Y - root.Position.Y)
		return horizontalDist <= ARRIVAL_RADIUS and verticalDist <= 3
	end
	return false
end

Call this check in a loop or use RunService.Heartbeat until it’s true.

  1. Use Waypoints from PathfindingService

If you’re using PathfindingService, it gives you waypoints. You can move the NPC toward each one, and after each movement, use the arrival check above.

for i, waypoint in ipairs(path:GetWaypoints()) do
	controllerManager:MoveTo(waypoint.Position)
	
	repeat
		RunService.Heartbeat:Wait()
	until hasReachedPosition(npc, waypoint.Position)
end

This mimics Humanoid:MoveTo() behavior pretty closely and works well with ControllerManager.


  1. ControllerManager Doesn’t Have Events — So You Need Polling

Unfortunately, as of now, ControllerManager doesn’t fire events like MoveToFinished. So yes — polling (looping + checking position) is currently the safest method unless Roblox adds more event-driven APIs in the future.

You can optimize your polling to avoid checking every frame — maybe check every 0.1 seconds using task.wait(0.1) instead of RunService.Heartbeat.

Bonus Tip: Add Debug Visuals!

When debugging NPC movement, it’s super helpful to visualize waypoints and destination zones using Part instances or drawing tools like DrawingService (via plugins).

:white_check_mark: Summary

• Use a radius-based position check (instead of raw magnitude every frame).
• For pathfinding, loop through waypoints and wait until each one is reached.
• Since ControllerManager lacks movement events, polling is necessary — but you can do it smartly.

Have you tested it enough times to be sure that the method is reliable?

Yes, I’ve tested this method (and several others) in real scenarios, and I can confirm that it’s quite reliable within the current limitations of ControllerManager. The region-based check (instead of relying solely on .Magnitude) has proven to be more stable and less prone to false positives caused by slight model jitters or physics updates.

That said, this is just a suggested approach — not the only way to handle arrival detection. The goal was to provide a solid and practical starting point that mimics Humanoid:MoveTo() behavior, especially since ControllerManager doesn’t fire movement-completion events.

There are definitely other valid methods depending on your needs (e.g., higher precision, performance optimization, custom pathing). The key is finding a solution that fits your project’s requirements.

Hope this gives you a useful base to work from.

1 Like

Okay, thanks for your help! I really appreciate that!

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