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.