Node Mapper for Pathfinding

As part of a larger project before I peace out again, I needed to create a node network system for custom pathfinding. I couldn’t use the Pathfinding service because I needed to restrict the network to certain areas. I also wanted to have multiple networked systems in the map.

And so I went a little crazy and built a plugin to do this for me. It lets me create nodes, connect them, and then import a pathfinder module to use for it.

The pathfinder “serializes” the nodes into Vector3 objects, with ObjectValues pointing to connected nodes.

I decided that I might as well release it because why not. I’m using this for an NPC system, but the below video shows a simplified use of it:

Plugin:

33 Likes

Looks great but I’m not sure it’s finding the optimal route. But then again that might not be your priority.
Surely this isn’t the shortest path?

image.jpg

image.jpg

Remember that in that particular instance I had broken the link to the right side, so it was forced left.

Also it is using a very basic heuristic (linear distance to end point). So I’m sure that could play into it too. Wouldn’t be hard to adjust the heuristic. (This is A* btw.)

Linear heuristics in A* like to stick to walls that are closest to the end point.

2 Likes

I could use this for a 3d space couldn’t I? Thinking of using this for AI in my space game.

Yes, absolutely! The pathfinder only cares about distances between points; doesn’t care about dimension.

A* only gives suboptimal solutions when the heuristic is more relaxed and it turns into a greedy search.

Doesn’t volcanoinc already have a plugin for this?

No idea. Wouldn’t be surprised if someone did. It’s really useful to have.

I do too :slight_smile:

Sorry to bother @sleitnick , but seems like after an update your plugin stopped working by an error with the custom Pathfinder module. I downloaded the version 13 and the custom module worked fine. Great plugin btw!

2 Likes

Thanks for the report. This has been fixed. Updating the plugin should bring in the fix.

2 Likes

I tried to use this but it gives me this error on the pathfinding module:
attempt to perform arithmetic (sub) on number and Vector3

function FindNearestNode(position: Vector3): Node
local dist, nearest = math.huge, nil
for _,node in ipairs(pathNodes) do
local d = (position - node.Position).Magnitude ← it happens here
if (d < dist) then
dist, nearest = d, node
end
end
return nearest
end

Can you fix that?

This is strictly for version 2 of the plugin

If you place all of the nodes down and then decide that you need to move the map than all the path data is useless.

This is a little script I wrote to allows you to move the paths with the map. Not particularly complicated but could save someone a little bit of time.

--Paste this code into the command bar BEFORE you move map
--RefPoint is a part that you put somewhere on the map
--When you move the map make sure that RefPoint moves with the map 
--When the movement is completed toggle the anchored property of RefPoint and Delete it 
--Set NodeMapName to the same name as the node map in the plugin 


local RefPoint = game.Workspace.RefPoint;
local NodeMapName = "Pathfinding"


local NodeMap = game.ReplicatedStorage.NodeMapProjects[NodeMapName];

for _,v in ipairs(NodeMap:GetChildren()) do
	local OrginalCFrame = CFrame.new(v:GetAttribute("NodePosition"));
	local RelativeCF = RefPoint.CFrame:ToObjectSpace(OrginalCFrame);
	local Connection;
	Connection = RefPoint:GetPropertyChangedSignal("Anchored"):Connect(function()
		Connection:Disconnect();
		v:SetAttribute("NodePosition",RefPoint.CFrame:ToWorldSpace(RelativeCF).Position);
	end)
end

2 Likes

Is this supposed to be used with the current Roblox pathfinding system or by itself with directing the humanoid with the :moveto() funtion?

1 Like

Hey @sleitnick I made a modification of this plugin by adding a grid option, I really liked your work but this feature was missing so I implemented myself! Feel free to use or upload this version since you are the owner of the project but pls give credits to me :grinning:
NodeMapPluginEdited.rbxm (23.3 KB)

2 Likes

How do i use the module?

Have an NPC I want to take a random path to a random node, any tips and pointers?

  1. Use Plugin (Plugin will help direct you).
  2. Then still in plugin, hit the Import Pathfinder(this will make a module script using that folder’s name).
  3. Make a script in Server scripts and put that module script in it(parent module to script).
  4. Put code :arrow_double_down: in the server script.

This code was taken from the Video above. Credits to sleitnick.

Code
local path = require(script.Pathfinder) -- get the pathfinder module script
local map = game.Workspace:WaitForChild("Map") -- change to Folder's name (with the nodes from plugin)

path:Init() -- do this first (important)

local gol = map:GetChildren()[math.random(1,#map:GetChildren())] -- gets random Node

local sta= -- start Position(change to humanoidRootPart I recon)
local gol = gol.Value -- Uses saved position in node (I have not tested this, so it might not work)

local rout = path:FindPath(sta,gol) -- calculates closest(not fastest) from start position to goal position
 
-- rout returns as a table with nodes' positions in it
if (rout) then -- shows path found (not necessary)
	print(rout)
	table.insert(rout,1,sta)
	table.insert(rout,gol)
	local seePFo = Instance.new("Folder",game.Workspace)
	seePFo.Name = "SeePathF"
	for i = 2,#rout do -- starts at two instead of one
		local p1 = rout[i - 1] -- goes back one to get previous
		local p2 = rout[i] -- current position
		local p = Instance.new("Part",seePFo) 
		p.Anchored = true
		p.TopSurface, p.BottomSurface = Enum.SurfaceType.Smooth, Enum.SurfaceType.Smooth
		--p.Material = Enum.Material.SmoothPlastic
		p.BrickColor = BrickColor.new("Neon orange")
		p.Size = Vector3.new(1,1,(p2-p1).Magnitude)
		p.CFrame = CFrame.new(p1:lerp(p2,0.5),p2)
	end
else
	print("no rout")
end

After that, Edit the code to work with a NPC.
something like:

local npc
local pathWay = require(script.Pathfinder)

for i = 1,#rout do -- starts at two instead of one
		local p1 = rout[i]
npc:MoveTo(p1)
npc.MoveToFinished:Wait(2)
end

:exclamation:Take Note​:exclamation: Code above may not work. If it does I’ll be shocked. :sweat_smile:
(short of like a little tutorial)
I hope this helps you, and Have a Blessed Day! :smiley:

1 Like