Start typing to search packages!
parallel-path
By @metricrb
Roblox
Mirroredparallel-path
Parallel Luau pathfinding for humanoids, vehicles, and custom rigs — no MoveToFinished stutter.
Why parallel-path?
SimplePath is great, but has one critical flaw: MoveToFinished event causes visible stuttering when humanoids reach waypoints. The event fires on the server after the client has already moved past the waypoint, creating noticeable jitter.
parallel-path solves this by replacing MoveToFinished with a Heartbeat distance-polling loop, borrowed from Roblox's ClickToMove controller logic. This eliminates stutter entirely.
Beyond that, parallel-path offers:
- Parallel path computation via Actors + Parallel Luau. Compute multiple paths at once without blocking gameplay.
- Multi-mode steering: Humanoid rigs, vehicles with PID steering, or completely custom controllers.
- Robust failsafes: Automatic recomputation on block, stuck detection with recovery, fallback to direct movement.
- No external dependencies: Signal and Promise are bundled.
- Comprehensive documentation: Full API reference, guides, and examples.
Quick start
Installation
Add to your wally.toml:
[dependencies]
ParallelPath = "metricrb/parallel-path@0.1"
Run wally install.
Basic usage
local parallel_path = require(game:GetService("ReplicatedStorage").Packages.ParallelPath)
local Agent = parallel_path.Agent
local Scheduler = parallel_path.Scheduler
-- Initialize once at game startup
Scheduler.init(4)
-- Create an agent for a humanoid NPC
local agent = Agent.new(workspace.MyNPC, {
steeringMode = "Humanoid",
})
-- Move to target
agent:MoveTo(workspace.Target.Position)
-- Handle events
agent.Reached:Connect(function(model, waypoint)
print("Reached target!")
end)
agent.Failed:Connect(function(model, reason)
print("Movement failed:", reason)
end)
See Getting Started for more.
Features
Heartbeat distance-polling
No more MoveToFinished stutter. The Agent reads the model's position every frame and compares it to the target waypoint distance. When close enough, the next waypoint is queued instantly.
Parallel path computation
Path requests run in Actor-isolated Parallel Luau, never blocking the main thread. Submit multiple paths at once — they compute in parallel.
Multi-mode steering
| Mode | Use case |
|---|---|
| Humanoid | NPCs, monsters, animated characters |
| Vehicle | Cars, tanks, with PID-controlled steering |
| Custom | AnimationControllers, TweenService, BodyVelocity, physics rigs |
Built-in stuck detection
If an agent doesn't move for 3 seconds, it automatically attempts a recovery jump (humanoids) or fires the Stuck signal. Configurable timeout and recovery strategy.
Failsafe hierarchy
When pathfinding fails:
- Automatically recompute (up to maxRetries)
- Attempt partial path to nearest reachable node
- Optionally fall back to direct steering
- Fire
Failedsignal with detailed reason code
Documentation
- API Reference — All methods, signals, and types
- Getting Started — Step-by-step walkthrough
- Guides — Vehicle steering, parallel computation, failsafes, migration from SimplePath
- Examples — Humanoid NPC, AI car, custom rig with BodyVelocity
Project structure
parallel-path/
├── src/
│ ├── init.luau -- Main export point
│ ├── Agent.luau -- Core movement controller
│ ├── Scheduler.luau -- Actor pool manager
│ ├── WorkerScript.server.luau -- Runs inside each Actor
│ ├── GridBuilder.luau -- Optional walkability grid
│ ├── Signal.luau -- Lightweight Signal (no BindableEvents)
│ ├── Promise.luau -- Minimal Promise implementation
│ ├── Types.luau -- Type definitions
│ └── Steering/
│ ├── HumanoidSteering.luau -- Humanoid:MoveTo() wrapper
│ ├── VehicleSteering.luau -- PID-controlled vehicle steering
│ └── CustomSteering.luau -- User-supplied callback
├── tests/
│ ├── Agent.spec.luau
│ ├── Scheduler.spec.luau
│ └── Steering.spec.luau
├── docs/
│ ├── index.md -- Overview
│ ├── getting-started.md -- Quick start
│ ├── api-reference.md -- Full API
│ ├── guides/
│ │ ├── vehicle-steering.md
│ │ ├── parallel-computation.md
│ │ ├── failsafe-hierarchy.md
│ │ └── migrating-from-simplepath.md
│ └── examples/
│ ├── humanoid-npc.luau
│ ├── ai-car.luau
│ └── custom-rig.luau
├── wally.toml
├── default.project.json
├── .luaurc
└── selene.toml
Performance
- Humanoid NPCs: 2–3x smoother due to Heartbeat polling (no MoveToFinished stutter)
- Many agents (10+): 5–10x faster with parallel computation
- Vehicles: New capability, significantly faster than humanoid pathfinding
- Memory: Slightly higher (Actor overhead), negligible for most games
Comparison with SimplePath
| Feature | SimplePath | parallel-path |
|---|---|---|
| Humanoid pathfinding | ✓ | ✓ |
| No MoveToFinished stutter | ✗ | ✓ |
| Parallel path computation | ✗ | ✓ |
| Vehicle steering | ✗ | ✓ |
| Custom steering callbacks | ✗ | ✓ |
| Stuck detection | ✗ | ✓ |
| Pause/resume | ✗ | ✓ |
| Recompute on block | ✓ | ✓ |
| Error signals | ✓ | ✓ (more detailed) |
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -am 'Add feature') - Push to the branch (
git push origin feature/my-feature) - Open a Pull Request
Testing
Run tests with:
wally install
rojo test
License
MIT — see LICENSE for details.
Acknowledgments
- Inspired by Roblox's ClickToMove controller for the Heartbeat polling approach
- Built with Luau strict mode for safety and type checking
- Designed for production games with performance in mind
Questions? Check the documentation or open an issue on GitHub.
Package Details
Install command (Click to copy)
Version
0.1.0
License
MIT
Safe for commercial use
Automated license review — not legal advice.
