He seems to be jumping a lot of times before successfully going down, any fixes I could do?
He sometimes also just walks back and jumps multiple times. I want to make him jump once and successfully do it.
function Update()
path:ComputeAsync(hrp.Position - Vector3.new(0, hrp.Size.Y/0.75, 0), ohrp.Position)
local wps = path:GetWaypoints()
table.remove(wps, 1)
coroutine.wrap(FollowOpponent)(wps)
end
function FollowOpponent(wps)
activecoroutine = coroutine.running()
for _, wp in ipairs(wps) do
if canrotate then
bodygyro.CFrame = CFrame.new(hrp.Position, ohrp.Position)
end
local check_distance = (hrp.Position - ohrp.Position).Magnitude
if check_distance > 4 then
if canmove then
if wp.Action == Enum.PathWaypointAction.Jump then
hum.Jump = true
end
hum:MoveTo(wp.Position)
hum.MoveToFinished:Wait()
end
elseif check_distance < 2 then
local dist = hrp.Position + (ohrp.Position - hrp.Position).Unit * -1 * 2
hum:MoveTo(dist)
end
end
end
one thing I see could be the issue is from where you wrap the FollowOpponent function in a coroutine
do you call update() while a FollowOpponent function is running?
you may have multiple FollowOpponent()s running at the same time where each one is making you jump
I believe the issue is that the jump waypoint is on the ledge, thus the NPC is jumping at the ledge and simply walking back onto it. You can fix this by making it walk to the next waypoint, which is guaranteed to be at the baseplate (unless you have a really low WaypointSpacing value or something), if it needs to jump in the current one:
if wp.Action == Enum.PathWaypointAction.Jump then
hum.Jump = true
hum:MoveTo(wps[i + 1].Position)
else
hum:MoveTo(wp.Position)
end
hum.MoveToFinished:Wait()
You will also need to modify the loop to receive the i variable, which is the waypoint’s index in the path (AKA where it is in the glorified list that is the table returned by Path:GetWaypoints). Also, why are you using ipairs? It doesn’t do anything different to pairs (a | b) which is no different to just not having iterator function at all because the waypoint list won’t have any “holes” (nil values) in it, because ipairs stops when it hits one of them, so you can change;
for _, wp in ipairs(wps) do
to:
for i, wp in wps do
One small nitpick I have is that your variable names are very short. You can very easily accidently type wps instead of wp, for example, which doesn’t happen with longer but more descriptive variable names like waypoint and waypointsList. It can also be easier for other people to understand your code when you post it here for help, because they are just more descriptive and “to-the-point” rather than three letters that don’t mean anything without context.
EDIT 25/08/2025: Fixed note about iteration order.
How often are you calling the Update function? Also, from the looks of it, there can be multiple instances of FollowOpponent running at once, maybe that could also be causing issues?
you need to adjust your code so that any existing FollowOpponent calls need to be cancelled when a new one runs
here’s a basic example of it
local currentId = -1
function update()
coroutine.wrap(followOpponent)()
end
function followOpponent()
local thisId = os.clock()
currentId = thisId
for i=1, 100, 1 do
task.wait()
if thisId ~= currentId then
print("Ended", thisId, "because a new followOpponent is running")
break
end
print(thisId, "doing step", i)
end
end
while task.wait(math.random() * 5)
update()
end
function FollowOpponent(wps)
activecoroutine = coroutine.running()
local thisId = os.clock()
currentId = thisId
for _, wp in ipairs(wps) do
if activecoroutine ~= coroutine.running() then return end
if thisId ~= currentId then break end
if canrotate then
bodygyro.CFrame = CFrame.new(hrp.Position, ohrp.Position)
end
local check_distance = (hrp.Position - ohrp.Position).Magnitude
if check_distance > 4 then
if canmove then
if wp.Action == Enum.PathWaypointAction.Jump then
hum.Jump = true
end
hum:MoveTo(wp.Position)
hum.MoveToFinished:Wait()
end
elseif check_distance < 2 then
local dist = hrp.Position + (ohrp.Position - hrp.Position).Unit * -1 * 2
hum:MoveTo(dist)
end
end
end
oh, the way you’re checking for the activeCoroutine now is doing the same thing as the ids, so you could take one of them out
as for why it’s still jumping, is it currently jumping one extra time after a jump for the pathfind is completed? in that case, it might be because setting .Jump while in midair makes the humanoid jump again after it lands (and then it doesnt stack any more than that because it’s already set to true)
if it’s jumping multiple times when it isnt close to somewhere it should jump, idk
if it’s jumping multiple times where each jump is too far from an edge it’s supposed to jump, maybe your pathfind interrupts are slowing the npc’s walking down too much. in this case, maybe only interrump when it’s strictly walking. this would allow users to cheese the npc by making up waste time going up and down ladders or swimming though, so you’ll have to watch for ways users can exploit it