(Legacy) SimplePath - Pathfinding Module

Latest version of SimplePath can be found below.


The SimplePath module gives you the ability to create a pathfinding script quickly and efficiently while also keeping your code well organized.
Current Version: 0.25
  • Path:Run() now returns true if the path is successful (make sure to handle this).
  • Fixed bug when pathfinding for humanoids with different sizes.
  • Removed the previous feature for IgnoreTimeout and made it built-in.
  • Fixed error that stops the Humanoid randomly.

local SimplePath = require(6336743234)

View API
Version History

Update 0.25:

  • Path:Run() now returns true if the path is successful (make sure to handle this).
  • Fixed bug when pathfinding for humanoids with different sizes.
  • Removed the previous feature for IgnoreTimeout and made it built-in.
  • Fixed error that stops the Humanoid randomly.

Update 0.24:

  • MAJOR FIX: Spamming Path:Run() and transition to new path is now seamless!
  • Fixed Path:Stop() from executing multiple times.
  • Fixed handling of more NetworkOwnership errors.

Update 0.23:

  • Fixed a bug involving NetworkOwnership.

Update 0.22:

  • SimplePath.new() saves the Path object at default. This can now be disabled (see api). Disabling this feature maximizes the performance but the Path object specific to the rig will not be retrievable (if the Path object was saved, it is automatically retrieved if you run Path.new() on the same rig).
  • Minor bug fixes.

Update 0.21:

  • Fixed a bug where the rig sometimes skipped waypoints if you use :Run() continuously.
  • Added a path visualize feature, use Path:Run(FinalPosition, true) to visualize the path.

Update 0.20:

  • Added a new feature where if you create a new Path object, it will check if it’s already been created and returns a previously Path object called on that same rig. This will avoid creating multiple Path objects on the same rig and therefore prevent memory leaks. Requested by @MohhayScripts .
Source Code

Basic Example

SimplePath Example.rbxl (40.7 KB)
(This is just a minimal example of what you can do with this module.)

local SimplePath = require(6336743234) --Get module

local Rig = workspace:WaitForChild("Dummy") --Get rig
local Part = workspace:WaitForChild("Part") --Define goal part
local Path = SimplePath.new(Rig) --Create new Path

Path:Run(Part.Position) --Start moving the Rig
Path.Completed:Wait() --Wait until Rig reaches the final position
Part.BrickColor = BrickColor.new("Bright green") --Change part color

Path:Destroy() --Destroy Path object after use
More Examples

Compute a new path instantly as the final position changes:

(Path:Run() is spam-proof and creates a seamless transition to the new path.)

View Script
local SimplePath = require(6336743234)

local Part = workspace:WaitForChild("Part")
local RunService = game:GetService("RunService")

local Rig = workspace:WaitForChild("Dummy")
local Path = SimplePath.new(Rig)

Part:GetPropertyChangedSignal("Position"):Connect(function()
	Path:Run(Part.Position)
end)

NPC:

(Quickly create a promising NPC simulation.)

View Script

(The script below is just a demonstration.)

local SimplePath = require(6336743234)

local Rig = workspace:WaitForChild("Dummy")
local Spawns = workspace.Spawns

for _, Block in pairs(Spawns:GetChildren()) do
	for i = 1, 100 do
		local Clone = Rig:Clone()
		Clone.Name = i
		
		local StartingPosition = Block:GetChildren()[math.random(1, #Block:GetChildren())].Position
		Clone:SetPrimaryPartCFrame(CFrame.new(StartingPosition))
		Clone.Parent = workspace
		
		local Path = SimplePath.new(Clone)
		Path.Humanoid.WalkSpeed = 5
		
		coroutine.wrap(function()
			local FinalPosition
			while true do
				FinalPosition = Block:GetChildren()[math.random(1, #Block:GetChildren())].Position
				if Path:Run(FinalPosition) then
					Path.Completed:Wait()
					wait(math.random(0, 5))
				end
				wait()
			end
		end)()
		
	end
end

Keybind Horse:

(Create a pet system in just a few lines!)

View Script
local Path = SimplePath.new(MountRig)
local Choices = {7, -7}
local FinalPosition = nil

while Path:Distance(HRP) > 8 do
	FinalPosition = (HRP.CFrame * CFrame.new(Choices[math.random(1, #Choices)], 0, 0)).Position + HRP.Velocity
	Path:Run(FinalPosition)
	Path.Completed:Wait()
end
Path:Destroy()

50 Likes

I noticed that you used PathfindingService which I suppose it the point of the module but maybe it would be nice if you made your own pathfinding without using the service just to increase performance for multiple humanoids. Although if the module was made for a beginners point in using pathfinding service easily, I would say it’s not bad. :grinning_face_with_smiling_eyes:

good luck

1 Like

The story is: I was working on my horse project (the same one in the example) and I needed to implement pathfinding on the horse. I already knew how long it would take to make an entire pathfinding script so I began searching for modules. Although there were some modules, I couldn’t really get them to function as I had hoped. After multiple tests with different modules, I decided to just go ahead and script pathfinding from scratch. Of course, after making the script, I immediately realized how chaotic it looked. I had to create a module for it.

I know many other developers may be facing a similar problem. Most developers don’t even bother using PathfindingService because it involves several parts of code to work properly. I made this module for those developers so they can easily implement PathfindingService without feeling overwhelmed by making it from scratch. So this is the main reason why I created this module. Perhaps I’ll make a custom pathfinding script in the future.

Anyway, thanks for your feedback! :grin:

2 Likes

Update 0.2:

  • Added a new feature where if you create a new Path object, it will check if its already been created and returns a previously Path object called on that same rig. This will avoid creating multiple Path objects on the same rig and therefore prevent memory leaks. Requested by @MohhayScripts .
3 Likes

This is awfully similar to my EZ Pathfinding V3 with almost the same functionality and function names. It pretty much includes everything that my module has. My module is basically a wrapper too and has some extra functionality. Even the purpose of this module is the same and I’m confused on why you’d go out of your way to recreate a module like mine when they, in the end, create the same exact thing. This isn’t meant to discourage you or anything but this is suspiciously similar to my module.

1 Like

I did use the EZ Pathfinding 3 module initially. I used the module and it didn’t work fully because it had some loose ends. In my horse project, it was hard to attain what I wanted using your module. Whatever I tried to do, the horse would still be buggy. I even went so far as to edit your script to make it work somehow, but editing something lead to something else. In the end, I ended up creating my own pathfinding script and that essentially lead me to create SimplePath. Furthermore, your module doesn’t have certain things like RBXScriptSignals that fire during specific instances so it’s incorrect to state that these two are even similar. The module that you made may seem like it is similar to mine, but that’s just because they both use common methods from PathfindingService. Under no circumstance is my module based or even remotely similar to the structure, code, and implementation of your module. Finally, I would like to conclude by saying that I did not at all create the same thing. I respect that you created your own module with your view of what needed to be included inside it. I have no idea how and why you made your module, but I have no reason to even care because my goal is not to recreate something that already is there. Everything I did making this module came from my own ideas and planning. Again, I respect your work completely and I hope this answers your question.

3 Likes

PathfindingService doesn’t depend on a humanoid, it only calculates a path between two points. I don’t think anybody will be able to create a more optimized pathfinding solution than roblox has with their service, either.

In terms of performance, most of the hit will come from moving the humanoid. Anybody looking to optimize a game that uses lots of humanoids that path should look at replacing the humanoid as an easy optimization step

5 Likes

You don’t need any humanoid. You can do nothing if you want with the path. The performance with PathFindingService is excellent as it is A* in C++, that is better than A* in sandboxed Lua

3 Likes

I am considering them similar since they share some function names and functionality. Besides that point they have different but slightly similar uses. One thing I suggest you add is more documentation of every function as beginners may not know how to properly use it.

You should perhaps make a public repo on Github making this open source, (for security reasons) as a developer would like to see what the code does under the hood.

1 Like

Yes, thank you for your suggestion. Sometime in the future, I plan to make a detailed api somewhere explaining everything in depth. It will come soon.

Sorry i wasnt clear. Thanks for your reply. :pray: what i meant with what i was trying to say was custom pathfinding for large amounts of humanoid. Obviously roblox’s service will lag with multiple humanoids like zombies. I meant a custom approach that will enable you to greatly improve performance by sacrificing certain things. Also to respond to your second part, when i said humanoid i meant moving humanoids with health and animations. Like you said roblox has the most optimized services because it is pure c++, so in most cases, trying to replicate things that already exist by yourself is likely a poor option. Thanks for the inpuy ill be leaving now. Feel free to respond in dms

It seems to have trouble pathfinding when dealing with unions. https://gyazo.com/c69c010a658556d488c5aa42ad9008c6 gray brick behind building is the goal, scary demon creature ramming into wall is using module. SDC is using R15 avatar type aswell.

It has no trouble with normal bricks though. what causes this to happen?
When putting goal behind a older version of building that didn’t use unions:
https://gyazo.com/0eb4cb3274b1b7339129cd1d8d00e057

I pushed an update to the module, see if that fixed the issue. Also when using custom characters, make sure you use Roblox’s PathParams to increase AgentRadius of the waypoints being generated. You can pass in PathParams as SimplePath.new(Rig, PathParams).

Works as intended. Thank you for making this module!

2 Likes

alright, when testing with SDC i have the following results:

when SDC uses new version, he suddenly stop using animations, however noncustom rigs keep their animations.

when moving the goal, SDC starts constantly stuttering towards it instead of walking smoothly towards it, but when testing with a noncustom rig it only stutters a little but not noticeably. https://gyazo.com/5c9d5bae7c2290564fafcc4f640c74f5

https://gyazo.com/a1671874fa5088e5b98f7b3c8f49654b?token=683028a69d6b8dd04d28b470fdd82993

I believe this may be because SDC has a LOAD of parts and some custom unions that make up the rig body parts since when testing with a noncustom rig it works fine.

Is there a way or a function to have the pathfinding ignore any parts in the parent rig? To add onto this it could be beneficial to have the pathfinding rig jump over any obstacles so it can’t be trapped in places that might have any parts/unions in the way.

Good work, and thank you in advance.

Hey, could I see your script for example you posted.

alright. Both models have used this same exact script.

local rig = workspace.hdfahjk
local SimplePath = require(6336743234)
local goal = workspace.Part

local Path = SimplePath.new(rig)

Path:Run(goal.Position)

goal:GetPropertyChangedSignal(“Position”):Connect(function()
Path:Run(goal.Position)
end)

Update 0.21:

  • Fixed a bug where the rig sometimes skipped waypoints if you use :Run() continuously.
  • Added a path visualize feature, use Path:Run(FinalPosition, true) to visualize the path.
    img.PNG
1 Like

Try the new update and see if it works.

1 Like