Version 1.3
Precise option
Interval option
Improved .Humanoid()'s Jump function
there’s this weird glitch where if the npc chases someone for a few seconds, the npc will stop moving
npc idle.rbxl (146.5 KB)
I am dumb, accidentally used “NoobPath.new” in a spot where I should’ve used “NoobPath.Humanoid” lmao
The reason why is because when NoobPath get the monster’s position, it get its primarypart’s position, the rootpart in this case. However, position doesn’t take consideration of the pivot offset. Although the rootpart’s pivot is on the ground, the rootpart’s position is high up in the air due to the monster’s height, while the player character, a normal rig have their rootpart position only a few studs above the ground. Making it impossible to reach.
local function getNearestTarget(npc, root)
local dist = 1000
local char
for _, player in pairs(game.Players:GetPlayers()) do
local vChar = player.Character
if vChar and vChar:FindFirstChild("Humanoid") and vChar:FindFirstChild("HumanoidRootPart") then
local vHum = vChar:WaitForChild("Humanoid")
local vRoot = vChar:WaitForChild("HumanoidRootPart")
if vHum.Health > 0 then
local magnitude = (vRoot.Position - root.Position).Magnitude
if magnitude <= dist then
dist = magnitude
char = vChar
end
end
end
end
return char
end
local npc = script.Parent
local ServerStorage = game:GetService("ServerStorage")
local NoobPath = require(ServerStorage.NoobPath)
-- you don't need to require Path, NoobPath is already using it
-- Define AgentParams for the NPC
local AgentParams = {
AgentRadius = 2, -- Example value
AgentHeight = 2, -- Example value
AgentCanJump = false,
-- AgentJumpHeight = 0, -- Roblox didn't implement this option, it does nothing
-- AgentMaxSlope = 45, -- Roblox didn't implement this option, it does nothing
Costs = {warning = 1}
}
-- Initialize NoobPath with AgentParams
local Guy, JumpDetectConnection = NoobPath.Humanoid(npc, AgentParams)
local designatedAreasFolder = workspace:WaitForChild("ai_zones")
local designatedParts = {}
-- Collect designated area parts
for _, part in ipairs(designatedAreasFolder:GetChildren()) do
if part:IsA("BasePart") then
table.insert(designatedParts, part)
end
end
-- Function to check if NPC is inside any designated area part
local function isInsideAnyPart(character)
for _, part in ipairs(designatedParts) do
local partPos = part.Position
local partSize = part.Size
local characterPos = character.HumanoidRootPart.Position
-- Check if the NPC is within the area of the part
local xRange = math.abs(characterPos.X - partPos.X) <= partSize.X / 2
local yRange = math.abs(characterPos.Y - partPos.Y) <= partSize.Y / 2
local zRange = math.abs(characterPos.Z - partPos.Z) <= partSize.Z / 2
if xRange and yRange and zRange then
return true
end
end
return false
end
Guy.Visualize = true
JumpDetectConnection:Disconnect()
-- runservice.stepped/heartbeat/renderstepped is pretty much the same as a loop, don't worry about the change
-- you don't need connections as you just repeat :Run() at a certain interval(ex: 0.1)
-- which is frequent enough
while task.wait(0.1) do
local target = getNearestTarget(npc, npc.HumanoidRootPart)
if target then
local targetRoot = target:WaitForChild("HumanoidRootPart")
-- Check if NPC is inside any designated area
if isInsideAnyPart(npc) then
-- Run towards target within designated areas
-- since you are not checking for trapped, (Timeout != true), there's no need to Jump to unstuck
-- also idle is just a state, by calling :Run(), idle automatically change to false
Guy:Run(targetRoot)
print("Ran")
else
-- Move directly to the target outside designated areas
if not Guy.Idle then
Guy:Stop()
end
npc.Hunt:MoveTo(targetRoot.Position)
print("Stopped")
end
end
end
I changed ur code a little bit
Version 1.4 will use PivotPosition instead
it still doesnt work, when you touch a wall and go around it, there is a chance where the npc will stop making paths and stop moving
I wish this module would exist earlier when I was making my own Pathfinding NPC using SimplePath. There’s a lot of things that it does well and also not. I’ve already modified a lot of SimplePath source code to fix those shortcomings.
Would you mind getting into detail about how NoobPath is different from SimplePath?
Since I believe that SimplePath already supports non-humanoid and other things similar.
Thank you for making SimplePath better, nonetheless.
Lastly, it would be amazing for this module to support some additional features of the new pathfinding update!
could you please send the new place, so I can test what’s going wrong, or tell me what changes did you make since the previous place you sent. Make sure you used Version 1.4
NoobPath have timeout feature, based on the speed(stud/s) of the agent and the distance between the waypoints, it will automatically calculate time required to travel between waypoints. If after that amount of time and the agent still didn’t reach the next waypoint, the Trapped signal will be fired, indicating that the agent is stuck. The Trapped signal also take in consideration of Humanoid:MoveTo() expiring after a certain threshold, firing if it was expired. Compared to SimplePath, it’s way easier to setup custom non-humanoid npcs in NoobPath, all you need is to put the desired functions and signals into the .new() constructor, can use the NoobPath object regularly. NoobPath also adjust waypoints by removing waypoints that are too close to each other, reducing the risk of getting stuck when trying to jump over an obstacle, which happens often in SimplePath. Other than that, it have some minor improvements in terms of delaying pathfinding while the character is in air (simplepath also does this, but more robust). I also added partial path into NoobPath, and there’s another feature called Precise, which prevent the character from continuing to the next waypoint while in air, slower movements but more accuracy for obby. It’s also more neat, with Path state represented by .Idle, a simple boolean. All methods also get autosuggested. NoobPath is basically SimplePath but more convenient, and the performance is only slightly more expensive.
Also if you found things that don’t work well, please give me suggestions.
it is the same file i gave before, to do the glitch, just go around the wall and go behind the npc and it will bug the pathfinding
I fixed that in 1.5 (forgot to add the PivotPosition in :Run())
Interval: No longer needed due to optimization of the Jump & WaitUntilLanded
Precise: Not great for performance in general, not very useful
fixed a problem with Server’s NetworkOwnership not working on Path Npc sometimes
optimized Jump & WaitUntilLanded
fixed PivotPosition not being used in :Run()
I got this error
ReplicatedStorage.NoobPath:172: attempt to index nil with 'Connect'
it says that the error is coming from NoobPath:Activate()
function NoobPath:Activate()
if Server then
self.DescendantAddedC = self.Character.DescendantAdded:Connect(function(Item)
if Item:IsA("BasePart") and Item:CanSetNetworkOwnership() then
Item:SetNetworkOwner(nil)
end
end)
end
-- ERROR AT THE LINE BELOW
self.MoveFinishedC = self.MoveFinished:Connect(function(Success) -- if you are using custom MoveFinished, Fire(true) if successfully reached
if self.Idle then
return
end
if Success then
local NextWaypoint = self:GetNextWaypoint()
if NextWaypoint then
self:TravelNextWaypoint()
self.WaypointReached:Fire(self:GetWaypoint(), NextWaypoint)
else
self:Arrive()
end
else
self:Stop()
self.Trapped:Fire("ReachFailed")
end
end)
self.JumpFinishedC = self.JumpFinished:Connect(function()
self.InAir = false
end)
end
It seems like you are using constructor .new() without MoveFinished signal given, which is why it caused an error. If you are using Humanoid, try .Humanoid() constructor.
local GS = require(workspace.NoobPath.GoodSignal)
local JumpS = GS.new()
local MoveS = GS.new()
local JumpC = JumpS:Connect(function()
print("JumpFinished")
end)
local MoveC = MoveS:Connect(function()
print("MoveFinished")
end)
local PrimaryPart = script.Parent.PrimaryPart
local AlignPos = Instance.new("AlignPosition")
AlignPos.Parent = PrimaryPart
local Attachment = Instance.new("Attachment")
Attachment.Parent = PrimaryPart
AlignPos.Attachment0 = Attachment
AlignPos.Mode = Enum.PositionAlignmentMode.OneAttachment
AlignPos.MaxForce = 25000
AlignPos.Responsiveness = 50
local Guy
Guy = require(workspace.NoobPath).new(
script.Parent,
{}, -- AgentParams
function(Pos)
print("Moved")
AlignPos.Position = Pos - PrimaryPart.PivotOffset.Position
local Break = false
local C
C = Guy.Overide:Connect(function()
C:Disconnect()
Break = true
end)
task.defer(function()
while not Break and (PrimaryPart:GetPivot().Position - Pos).Magnitude > 2 do
task.wait()
end
if not Break then
MoveS:Fire(true)
end
end)
end,
function()
-- Custom jumping is complex, I won't implement it in this example
JumpS:Fire()
end,
JumpS,
MoveS
)
Guy.Visualize = true
Guy:Run(workspace.SpawnLocation)
while task.wait(0.1) do
Guy:Run()
end
Does this mean we should not turn on the new feature, or is the new feature compatible with Noobpath?
Also anyway of having an open source testing place?
Thanks
the new features are compatible, what I mentioned are features NoobPath offer/improvements to SimplePath
Ok, thanks,
what about a testing place, where the npc have different capabilities… like some are fast and smart, some are slow and smart , some are fast and not so smart…
can different NPCs have different things like above?
NoobPath is just Pathfinding service but simplified and improved. What you mentioned are specific behaviors that will require custom logic and has to be implemented by you.
mm ok… seems like it would be cool to have in noobpath…
is there any kind of global debugging that can be turned off and on… like to see what it is doing when testing things out, but being able to toggle it off at other times?
you can turn visualize on, and add connection to the error, jumpfinished, movefinished, overide, trapped, reached, waypoint reached… events to detect what is happening