So, I have been using this module for a while. I change absolutely nothing and suddenly it stops working. What happens is the NPC doesn’t move. Here is my code:
task.spawn(function()
while true do
task.wait(0.1)
path:SetHipHeight(1)
path:Run(character.PrimaryPart)
end
end)
Its probably because of the time out added in the module if you updated to a newer version so by commenting
coroutine.wrap(function()
while self._active do
if self._elapsed and tick() - self._elapsed > 1 then
Timeout(self); break
end
RunService.Stepped:Wait()
end
end)()
wait(5)
local SimplePath = require(game.ServerScriptService.SimplePath)
local closestplrdis = nil
local plrHead = nil
while true do
for _, v in pairs(game.Players:GetChildren()) do
if closestplrdis == nil then
if v.Character:FindFirstChild("Head") then
closestplrdis = (script.Parent.Head.Position - v.Character.Head.Position).Magnitude
plrHead = v.Character.Head
end
else
local plrdistance = (script.Parent.Head.Position - v.Character.Head.Position).Magnitude
if plrdistance < closestplrdis then
closestplrdis = plrdistance
plrHead = v.Character.Head
end
end
end
local Path = SimplePath.new(script.Parent)
Path:Run(plrHead)
wait()
end
Be awesome if you could have a variable that contains how many studs (0.1, 1, 1+) away from the goal the NPC should stop. You could modify the pathfinder return results last waypoint and deduct some distance from it? This would allow us to stop the NPC a measurable distance from the goal and do some animations (kick\punch). It’d also stop the crowding\jumping on top of the goal when the NPC arrives.
That’s a very good suggestion. But in my opinion, you can easily stop pathfinding when the NPC is a certain distance from the goal. Off the top of my head, one of the ways I could think of is by performing magnitude checks using the Path.WaypointReached event whenever the NPC reaches the next waypoint. I’m sure there are many other ways you can go about achieving this easily. It mostly depends on how your code is structured.
Yes it’d be useful to allow for some range wouldn’t it.
I think WaypointReached would be too late, here’s a simplfied rendition of how I worked the idea into my adoption of your module code.
if Goal then
if (script.Parent.PrimaryPart.Position - Goal.Position).Magnitude > 10 then
Path:Run(Goal)
else
if Path["_status"] == "Active" then -- So that we do not invoke stop more than once or it errors
Path:Stop()
end
end
end
Be cool to integrate this into the module script, I’m calling the Path:Run repeatedly so there’s an opportunity for the modulescript to detect distance and do a stop while the humanoid is moving and before it reaches the waypoint, then start ignoring Path:Run calls until distance isn’t restricting.
I modified your code, hope you don’t mind me showing examples and modding it like this, I need this built-in and configurable per-NPC.
The Path:Run function just needed a slight modification by adding DISTANCE_TO_STOP as a param being passed, and some code for it to all work
function Path:Run(target, DISTANCE_TO_STOP)
-- NEW CODE
if DISTANCE_TO_STOP then -- Check if magnitude at or below DISTANCE_TO_STOP
if (target and self._agent and self._agent.PrimaryPart) and (self._agent.PrimaryPart.Position - target.Position).Magnitude <= DISTANCE_TO_STOP then
if self._status ~= Path.StatusType.Idle then
self:Stop()
return
end
return
end
end
-- NEW CODE
Path:Run is invoked as usual, or you can add the extra param to enable the behaviour:
I know I said I’ll consider adding this feature in. However, that was before I realized some important details. Allow me to explain. Now the most common method of doing something like would be to compare the magnitude of the vector between the NPC’s PrimaryPart position and the target position. If I implement this feature in the module, SimplePath wouldn’t account for the sizes of either the PrimaryPart or target and this can result in undesired behaviour by incorrect distance results.
The second option would be to perform checks on the waypoints instead of the actual NPC or target. This can prove to be a better solution, but there is a downside of using this method. Imagine a platform with another platform directly above it and both are connected by stairs. The NPC is on the lower platform and tries to navigate up the stairs to reach the next platform to its target. Now when the NPC is on the lower platform, and the script detects that the waypoint distance to the target is lower than a certain value, it’ll end up removing the waypoints on the lower platform because those waypoints are closer to the target. Furthermore, this problem also exists for the very first method.
The best immediate solution would be to give the user the opportunity to perform distance checks on their own which can prove to be a more precise method because the user is aware of the dimensions of the NPC and will do the checks accordingly. Alternatively, a possible theoretical solution to these problems would be to iterate over the waypoints and compare the distance by taking into account the waypoint’s unit vector pointing to the consecutive waypoint. Maybe I will implement something like this in the future. But for now, I think it’s best to let the user handle the distance checks on their own.
I’m okay with this not being adopted, I stumbled upon your script and needed to fit it into my project in the most suitable way and posted the changes.
I like how it was written SimplePath, very clean and understandable code.
An obserable problem with PathFinding is that it puts the NPC on the goal, so NPC’s pile up. I wanted them to stop a short distance away from the goal, a magnitude of 5 or less, SimplePath now handles that for me while a movement script does checks for 5 or less and performs the animations needed for combat. Overal it works quite well. I have some funky behaviour from scaled up NPC’s that get snagged in non-complex scenery, I was going to go back later today when I begin coding and have a look at how your script is handling hipheight.
I also had to brace with additional error checking the ComparePosition function, here:
local function comparePosition(self)
if self._currentWaypoint == #self._waypoints then return end
-- NEW CODE
if self._agent and self._agent.PrimaryPart and self._position then -- Validation check added by me
-- NEW CODE
I’ll keep an eye on your updates and fit my changes in where needed, Thanks again!
In the previous version of the module, I may have used HipHeight for some calculations but it essentially turned out to be unreliable because not all humanoids have a hip height. Luckily, this module doesn’t have anything to do with HipHeight. With custom characters (or custom scaled in this case), the fix to weird behaviour might simply be to adjust your agent parameters according to your character (this was the case during the testing stage of SimplePath). I hope the behaviour you mentioned with scaled humanoids is fixed in this way. Let me know if that weird behaviour still persists even after the adjustments, I’m curious to know.