Setting up a solid roblox pathfinding script is one of those things that seems simple until your NPC starts walking directly into a brick wall or spinning in circles. We've all been there—you just want a basic enemy or a helper bot to follow the player, but instead, it gets stuck on a pebble. The good news is that Roblox actually has a pretty powerful built-in system called PathfindingService that does the heavy lifting for you. You don't have to manually calculate every single turn or worry about the math of a 3D grid, but you do need to know how to talk to the API so it doesn't do something weird.
Getting started with the PathfindingService
If you're just using Humanoid:MoveTo(), you're going to run into trouble the second there's an obstacle in the way. MoveTo is basically just a "walk in a straight line" command. To get around corners, your roblox pathfinding script needs to use the actual service that calculates a route.
The first thing you've gotta do is get the service at the top of your script. It's a standard game:GetService("PathfindingService") call. From there, you create a "path" object. This object is like a blank map that hasn't been drawn on yet. You tell it where the NPC is starting, where it's going, and then the service spits out a bunch of points—called waypoints—that the NPC should follow to get there safely.
The mistake a lot of people make early on is not considering the "Agent Parameters." When you create a path, you can actually pass a table of settings. This is huge. If your NPC is really big, or if they can jump really high, you need to tell the script that. Otherwise, the pathfinder might try to squeeze a giant boss through a tiny doorway, and your NPC will just jitter against the wall until it times out.
Writing the actual script logic
When you're ready to actually move something, you'll be using the ComputeAsync function. It sounds fancy, but it just means "calculate the path right now." You give it a start position and an end position. Once that's done, you check if the path was actually successful. Roblox uses an Enum.PathStatus.Success check for this. If it failed, maybe the player is standing on a platform the NPC can't reach, or maybe they're just too far away.
Once you have a successful path, you get a list of waypoints using path:GetWaypoints(). This is basically a list of coordinates. You'll want to loop through this list and tell the Humanoid to move to each one in order.
A little trick that I always recommend is visualizing these waypoints while you're debugging. Just have the script spawn a tiny, glowing neon sphere at each waypoint position. It makes it way easier to see why your NPC is taking a weird route or where it's losing the trail. If you see the dots going through a wall, you know your navigation mesh is messed up. If the dots stop halfway, you know the calculation failed.
Dealing with corners and getting stuck
One of the biggest headaches with a roblox pathfinding script is the "stuck" factor. NPCs are notoriously bad at navigating tight corners if the pathfinding isn't updated frequently enough. Because players move constantly, a path that was valid a second ago might be totally useless now.
You generally have two ways to handle this. You can either recalculate the path every time the NPC reaches a waypoint, or you can do it on a timer. Recalculating too often will kill your game's performance, but recalculating too slowly makes the NPC look like it has a five-second delay. I usually find that checking the distance between the NPC and the player every half-second or so is a good middle ground. If the player has moved more than a few studs, it's time to run ComputeAsync again.
Also, don't forget about the Blocked event. The PathfindingService has an event that fires if something new (like a falling part or a door closing) blocks the path the NPC was currently following. It's a lifesaver. Instead of the NPC walking into the new obstacle, the script catches the event and forces a path recalculation immediately.
Performance tips so your game doesn't lag
If you have fifty NPCs all running a complex roblox pathfinding script at the same time, your server's heart rate is going to spike. Pathfinding is expensive. To keep things running smoothly, you've got to be smart about how often you ask the server to think.
First off, don't run pathfinding if the target is in a straight line of sight. You can use a simple Raycast to check if there are any parts between the NPC and the player. If the ray hits the player directly, just use MoveTo() and skip the pathfinding entirely. It's way cheaper.
Secondly, consider the distance. If an NPC is 500 studs away from a player, does it really need to calculate a perfect path right now? Probably not. You can put the script to sleep or use a very simple "walk toward" logic until the player gets closer. Only start the heavy-duty pathfinding when it actually matters for the gameplay.
Another thing to look at is the WaypointSpacing in your agent parameters. By default, Roblox drops a waypoint every 4 studs or so. If you increase that distance, the NPC has fewer points to process, which can save a bit of overhead, though it might make their movement look a little more "point-to-point" and less fluid.
Adding some polish to the movement
Once you've got the NPC moving from point A to point B without hitting a wall, you might notice it looks a bit robotic. It stops for a split second at every waypoint, making its movement look jerky.
To fix this, most developers don't wait for the MoveToFinished event for every single waypoint. Instead, they check the distance to the next waypoint inside a loop. Once the NPC is within maybe 2 or 3 studs of the current waypoint, the script immediately tells it to start moving to the next one. This creates a much smoother, curved movement pattern because the Humanoid doesn't have time to come to a full stop.
You should also look into the "Jump" action. Waypoints have an Action property. If the pathfinder thinks the NPC needs to jump to reach the next point, the action will be set to Enum.PathfindingJumpAction.Jump. Make sure your script actually checks for this! It's a classic mistake to write a whole roblox pathfinding script and then wonder why the NPC just stares at a 2-foot tall ledge like it's an impossible mountain.
Final thoughts on implementation
At the end of the day, a roblox pathfinding script is only as good as the environment it's in. If your map is full of "Unanchored" parts and messy collisions, the pathfinding is going to struggle. Make sure your "Navigation Mesh" is clean. You can actually view the NavMesh in the Studio settings—it'll show you exactly where the engine thinks an NPC can and cannot walk.
Don't be afraid to experiment with the AgentCanJump and AgentRadius settings. Every NPC is different. A tiny spider bot needs different pathing than a massive zombie. It takes a bit of tweaking to get the feel right, but once you get that logic dialed in, it completely changes the vibe of your game. Suddenly, your world feels alive because things are actually interacting with the space instead of just gliding through it. Just keep an eye on that server micro-profiler, stay away from infinite loops without waits, and your NPCs will be hunting down players like pros in no time.