EZ Pathfinding V2 [OUTDATED]

Recently I have been working a lot with the Pathfinding service and noticed it took quite a bit of time and about 50 lines of code. Today I decided to make a custom pathfinding API from scratch. It uses the normal roblox pathfinding, but only requires about 2 lines of code. It is very simple to use, especially if you are a beginner and saves you a lot of time.

If you would like to set it up you can require it.

Here is an example of how to use it:

local pathfinding = require(5575093153)

pathfinding:SetParams(2, 5, true) -- AgentRadius, AgentHeight, AgentCanJump

pathfinding:Move(script.Parent, game.Workspace.Destination) -- npc, destination

pathfinding:WalkSpeed(script.Parent, 25) -- npc, WalkSpeed number

pathfinding:JumpPower(script.Parent, 70) -- npc, JumpPower number

pathfinding:Jump(script.Parent) -- npc

You can get the module here:
https://www.roblox.com/library/5575093153/EZ-Pathfinding-V2

If you have feedback, suggestion or questions, you can reply to this thread or message me.

Details
Why Should I use EZ Pathfinding V2?

EZ Pathfinding make pathfinding a whole lot easier to use pathfinding and has built in functions that can make a NPC perform specific actions. It can be modified to your what you wish, which makes it more flexible to use. EZ Pathfinding not only controls NPCs, but also makes tweening a mass load of parts easier.

EZ Pathfinding V3

EZ Pathfinding was just released. You can find the thread here: EZ Pathfinding V3 [OUTDATED]

.
.

Source Code
--// Variables
local pathfinding = {}

local pfservice = game:GetService("PathfindingService")

local waypoints = {}

local currentwaypointindex = 1

local partwaypoint = 1

local tservice = game:GetService("TweenService")

local partwaypoints = {}

local currenttweenpart

local currentendpart

local touched = false

local ptpause = false

local stopped = false

--//Table Functions
pathfinding.DestinationReached = {}

--//Tween Info
local tweeninfo = TweenInfo.new(
		5,
		Enum.EasingStyle.Linear,
		Enum.EasingDirection.In,
		0,
		false,
		0
)

local settweeninfo

--// Functions
function pathfinding:Jump(npc, toggle)
	if npc then
		if self.ACJ == true then
		if npc:FindFirstChildOfClass("Humanoid") then
			local humanoid = npc:FindFirstChildOfClass("Humanoid")
			humanoid.Jump = toggle
				self.Jumping = toggle
				end
		end
	end
end

function pathfinding:WalkSpeed(npc, number)
	if number == nil then
		else
	if npc:FindFirstChildOfClass("Humanoid")then
		local hum = npc:FindFirstChildOfClass("Humanoid")
		hum.WalkSpeed = number
		end
		end
end

function pathfinding:JumpPower(npc, number)
	if number == nil then
		else
	if npc:FindFirstChildOfClass("Humanoid")then
		local hum = npc:FindFirstChildOfClass("Humanoid")
		hum.JumpPower = number
		end
		end
end

function pathfinding:SetParams(agentradius, agentheight, agentcanjump)
	self.AR = agentradius or 2
	self.AH = agentheight or 5
	self.ACJ = agentcanjump or true
end

function pathfinding:Move(npc, endpart)
	if npc ~= nil then
		local path = pathfinding:CreateNewPath(npc, endpart)
		path:ComputeAsync(npc.HumanoidRootPart.Position, endpart.Position)
		local hum
		waypoints = path:GetWaypoints()
		if npc:FindFirstChildOfClass("Humanoid")then
			hum = npc:FindFirstChildOfClass("Humanoid")
		end
	
	if path.Status == Enum.PathStatus.Success then
			if hum ~= nil then
				hum:MoveTo(waypoints[currentwaypointindex].Position)
				hum.MoveToFinished:Wait()
			end
		else
			hum:MoveTo(npc.HumanoidRootPart.Position)
			end
	else
		print("No npc to move.")
		end
end

local function onWaypointReached(reached, npc)
	local humanoid = npc:FindFirstChildOfClass("Humanoid")
	if typeof(pathfinding.DestinationReached) == "function" then
		pathfinding.DestinationReached()
		end
	if reached and currentwaypointindex < #waypoints then
		currentwaypointindex = currentwaypointindex + 1
		humanoid:MoveTo(waypoints[currentwaypointindex].Position)
	end
end

local function onPathBlocked(blockedWaypointIndex, npc, endpart)
	if blockedWaypointIndex > currentwaypointindex then
		pathfinding:Move(npc, endpart)
	end
end

--[[local function onPartBlocked(blockedWaypointIndex, npc, endpart)
	if blockedWaypointIndex > partwaypoint then
		pathfinding:TweenPart(npc, endpart)
	end
end--]]

function pathfinding:CreateNewPath(npc, endpart)
	local params = {AgentRadius = self.AR, AgentHeight = self.AH, AgentCanJump = self.ACJ}
	local path = pfservice:CreatePath(params)
	local hum = npc:FindFirstChildOfClass("Humanoid")
	if hum ~= nil then
path.Blocked:Connect(onPathBlocked, npc, endpart)
		hum.MoveToFinished:Connect(function(status)	
		onWaypointReached(status, npc)
		end)
		end
	return path
end

function pathfinding:Pause(npc)
	for i,v in pairs(npc:GetChildren())do
		if v:IsA("MeshPart")or v:IsA("Part")then
			v.Anchored = true
		end
	end
end

function pathfinding:ResumePath(npc)
	for i,v in pairs(npc:GetChildren())do
		if v:IsA("MeshPart")or v:IsA("Part")then
			v.Anchored = false
		end
	end
end

function pathfinding:PartMovement(npc, parttable)
	pcall(function()
		local currentpart = 1
		local debounce = false
	local hum = npc:FindFirstChildOfClass("Humanoid")
		local part = parttable[currentpart]
		hum:MoveTo(part.Position)
		part.Touched:Connect(function()
			wait(self.PartMovementWaitTime or 0)
			if debounce == false then
			debounce = true
			currentpart = currentpart +1
		local newpart = parttable[currentpart]
				hum:MoveTo(newpart.Position)
				wait(3)
				debounce = false
				end
			end)
		end)
end

function pathfinding:StopPath(npc)
	pathfinding:Move(npc, npc.HumanoidRootPart)
end

function pathfinding:PartMovementWait(number)
	self.PartMovementWaitTime = number
end

--[[local function onTweeningReached(reached, part)
	if reached == true and partwaypoint < #partwaypoints then
		partwaypoint = partwaypoint + 1
		for i = 0, 1, 0.05 do
	local Goal = {Position = partwaypoints[partwaypoint].Position}
	local tween = tservice:Create(part, tweeninfo, Goal)
			tween:Play()
			end
	end
end--]]

function pathfinding:TweenPart(part, endpart)
	spawn(function()
		self.canTweenOldPath = true
		self.StoppedPath = false
		self.ptpause = false
		stopped = false
	currentendpart = endpart
	currenttweenpart = part
local path = pfservice:CreatePath()
path:ComputeAsync(part.Position, workspace.Part.Position)
	local waypoints = path:GetWaypoints()
	local currentpartt

	for i, waypoint in pairs(waypoints) do
			wait(1)
			if self.canTweenOldPath == true then
				if self.ptpause == false then
					local newpart = Instance.new("Part")
	newpart.Position = waypoint.Position
	newpart.Size = Vector3.new(0.6,0.6,0.6)
	newpart.Shape = "Ball"
	newpart.Anchored = true
		newpart.CanCollide = false
		newpart.Name = "Waypoint"
		newpart.Parent = workspace
		newpart.Transparency = 1
		
		currenttweenpart = part
		
		newpart.Touched:Connect(function(hit)
			touched = true
			wait(3)
			touched = false
				end)
				end
				end
		end
		end)
end

game.Workspace.ChildAdded:Connect(function(new)
	--coroutine.create(function()
	pcall(function()
		--if ptpause == false then
	local part = currenttweenpart
	if new.Name == "Waypoint" then
			local goal = {Position = new.Position}
			local tween = tservice:Create(part, tweeninfo, goal)
			tween:Play()
			if stopped == true then
				tween:Cancel()
			end
			end
			--end
		--end)
		end)
end)

function pathfinding:DestroyAllWaypoints()
	coroutine.create(function()
	local waypointsintotal = 0
	local work = game:GetService("Workspace")
	local debris = game:GetService("Debris")
	
	for i,v in pairs(work:GetChildren())do
		if v.Name == "Waypoint" then
			waypointsintotal = waypointsintotal +1
			debris:AddItem(v)
		end
		end
		end)
end

function pathfinding:SetTweenInfo(numtime, easingstyle, easingdirection, repeatcount, reverses, delaytime)
	coroutine.create(function()
	tweeninfo = TweenInfo.new(
		numtime,
		easingstyle,
		easingdirection,
		repeatcount,
		reverses,
		delaytime
		)
		end)
end

function pathfinding:PartReachedWaypoint()
	currenttweenpart.Touched:Connect(function()
		return true
	end)
end

function pathfinding:UpdatePath(npc, endpart)
	if npc ~= nil then
		local path = pathfinding:CreateNewPath(npc, endpart)
		path:ComputeAsync(npc.HumanoidRootPart.Position, endpart.Position)
		local hum
		waypoints = path:GetWaypoints()
		if npc:FindFirstChildOfClass("Humanoid")then
			hum = npc:FindFirstChildOfClass("Humanoid")
		end
	
	if path.Status == Enum.PathStatus.Success then
			if hum ~= nil then
				hum:MoveTo(waypoints[currentwaypointindex].Position)
				hum.MoveToFinished:Wait()
			end
		else
			hum:MoveTo(npc.HumanoidRootPart.Position)
			end
	else
		print("No npc to move.")
		end
end

function pathfinding:TweenPartNoControl(part, endpart)
	self.canTweenOldPath = false
	currentendpart = endpart
	currenttweenpart = part
local path = pfservice:CreatePath()
path:ComputeAsync(part.Position, workspace.Part.Position)
	local waypoints = path:GetWaypoints()
	local currentpartt

	for i, waypoint in pairs(waypoints) do
		wait(1)
		
	local newpart = Instance.new("Part")
	newpart.Position = waypoint.Position
	newpart.Size = Vector3.new(0.6,0.6,0.6)
	newpart.Shape = "Ball"
	newpart.Anchored = true
		newpart.CanCollide = false
		newpart.Name = "Waypoint"
		newpart.Parent = workspace
		newpart.Transparency = 1
		
		currenttweenpart = part
		
		newpart.Touched:Connect(function(hit)
			touched = true
			wait(3)
			touched = false
		end)
	end
end--]]

function pathfinding:PausePartPath()
	self.ptpause = true
	ptpause = true
end

function pathfinding:ResumePartPath()
	self.ptpause = false
	ptpause = false
end

function pathfinding:StopPartTweening()
	self.StoppedPath = true
	stopped = true
end

return pathfinding

I will update this every week and keep an update log for all of you to see.

Update Log:
8-17-20 - Part Movement : Example

local parts = {
	[1] = -- part 1
    [2] = -- part 2
}
pathfinding:PartMovement(script.Parent, parts) -- npc, part table

8-16-20 - Stopping the Current Path : Example

pathfinding:StopPath(script.Parent)

8-17-20 - Pausing between part movement : Example

pathfinding:PartMovementWait(wait time) -- change wait time to how long before moving on to the next part

8-18-20 - Part Tweening With Pathfinding : Example

pathfinding:PartTween(script.Parent, game.Workspace.Destination) -- part that's being tweened, destination

script.Parent.Touched:Connect(function(hit)
if hit.name == game.Workspace.Destination.Name then
pathfinding:DestroyAllWaypoints() -- suggested to be used as not using it can get a little messy
end
end)

8-19-20 - Customizing Tween Info : Example

pathfinding:SetTweenInfo(5, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0)

This works, however for some reason it prints an error. If you can, ignore that error if you are using this.
8-22-20 - Fixed part tweening. It had to do with the coroutine I added in the last update.
/
Updating the npc’s current path : Example

pathfinding:UpdatePath(npc, end part) -- describes the info of the path you want to be updated.

8-25-20 - Pausing and resuming part tweening : Example

pathfinding:PausePartPath()

pathfinding:ResumePartPath()

/
Updating the part’s path : Example

pathfinding:UpdatePartPath(start part, end part)

8-26-20 - Stopping a part’s tweening : Example

pathfinding:StopPartTweening()

Stops the current part’s tweening.

9-9-20 - Made npc part movement much more efficient and time consuming. (Read the updated version in the update log section explaining it.)

9-11-20 - Destination Reached : Example

pathfinding.DestinationReached = function()
--code
end
  • I love this module! No feedback.
  • I like it but I have feedback (EXPLAIN).
  • I have a lot of feedback (EXPLAIN).

0 voters

Only vote if you have tried the plugin!

Video on how to use:

Notes:

  • EZ Pathfinding currently cannot move two rigs from one script.
46 Likes

Please can you provide a gif / video of this in action

4 Likes

That makes life so much easier🤯
However, i would suggest you also provide basic functions that would handle
Path has obstacle
Path update/refresh (new pos or nil to recalculate path)
and maybe Path stop (stop moving along path)

Then tbe module will definetaly have a great use!
Path

4 Likes

I just added a pause a resume function. I will try making a stop function to stop the path entirely. Your suggestions should come out within the next few days! Thanks for the feedback! :grinning:

1 Like

My recording software isn’t compatible with the dev forum. I might try Gyazo.

1 Like

Okay, I just released the stop function. You can now stop the current path and create a new one! There is also already a line of code that handles obstacles. Your other suggestions may come later today or sometime in the next week.

2 Likes

I might try making a refresh/update path function later on today. I just created a youtube tutorial on how to use this module if you want to look at it to get a better understanding of the module.

1 Like

You have forgotten to implement the video link to thw tutorial

2 Likes

Ah sorry, it is being uploaded right now. When it is finished, I will link it.

1 Like

If you have any questions or suggestions regarding the module, please make sure to tell me. Your stop function came out very useful and I think it helps the community more.

1 Like

Here is the youtube video link:

3 Likes

Pausing between part movement added! You can now set the wait time that the npc has to wait before moving onto the next part. (Can only be used for part movement.)

New Update! You can now tween parts using pathfinding. The part will tween towards its destination while avoiding obstacles. More settings for this to come soon! Enjoy this new update!

1 Like

Woo hoo! Another update has come to EZ Pathfinding V2! Now you can change the tween info with one line of code. (So far tweening only works with singular parts.) Enjoy messing around with different easingstyles and directions, time, reverses and so much more! :grinning:

1 Like

Cool module! I might use it when I need to use pathfinding, but currently I don’t.

Maybe this could be used for a parkour type game to make a ghost run the course to show you how its done (maybe for a tutorial…?)

4 Likes

I also suggest you learn OOP basics and convert this wonderful module into one
So then this would work

local PathfindingModule = require(5575093153)
PathfindingModule:SetParams(2, 5)
local newPath = PathfindingModule.new(NPC or PART)
newPath:MoveTo(target location)
newPath.AutoUpdatePathOnObstacle = true
newPath.DestinationReached:Connect(function()
   newPath:Stop()
   newPath:Remove()
end)
etc....
4 Likes

I was actually already planning to make a DestinationReached function. The RefreshPath function should come soon.

2 Likes

DestinationReached function ? How is that going to work lol?

3 Likes

Whenever say the npc reaches a point, you can call that using that function. Then put your lines of code under it. This time each time it reaches a point, it can do something. It times it out much better than using the wait function.

1 Like

Also by the way, you don’t need to use the SetParams function if you are going to leave them as they are by default. If you do use that function make sure to add the agentcanjump part as that can cause jumping to not work. Example: pathfindingModule:SetParams(2, 5, true) Instead of: