Anything in spoilers means that it was old and is not accurate now.
- What do you want to achieve?
I want to fix my pathfinding script so it can jump when needed
I want to fix my pathfinding script, making it smooth and usable.
- What is the issue?
I have a dummy that I made follow a player. If I ever go on top of something that you can jump on top of, the dummy just walks into it without jumping.
It is not very smooth and it also can get stuck and start spasming.
- What solutions have you tried so far?
I’ve made sure AgentCanJump = true. For some reason, the problem doesn’t occur with my version of the pathfinding (It is very choppy so I didn’t use it) but it occurs with code I took from the Roblox dev articles and modified.
I have tried reducing how many times update is fired by putting it into a while wait() loop. didn’t improve anything (Honestly it seemed worse?). I have set the network owner to the server (AKA. nil).
EDIT: I have rewritten the script and it somewhat works. The dummy will jump but now it cannot successfully follow me as if it is having a seizure.
OLD
local function GrabTarget()
local playertable = game.Players:GetChildren()
local target
local targetmag
for i, player in pairs(playertable) do
local char = player.Character or player.CharacterAdded:Wait()
local rootpart = char.HumanoidRootPart
local mag = math.round((rootpart.Position - script.Parent.HumanoidRootPart.Position).Magnitude*10^(3))/10^(3)
if target == nil or mag < targetmag then
target = player
targetmag = mag
end
end
return target
end
local PathfindingService = game:GetService("PathfindingService")
-- Variables for the zombie, its humanoid, and destination
local zombie = script.Parent
local humanoid = zombie.Humanoid
local destination = GrabTarget()
local lastknowntarget
local lastknownpos
local runservice = game:GetService("RunService")
zombie.PrimaryPart:SetNetworkOwner(nil)
local pathparams = {}
pathparams.AgentCanJump = true
pathparams.AgentHeight = 6
pathparams.AgentRadius = 2
-- Create the path object
local path = PathfindingService:CreatePath(pathparams)
-- Variables to store waypoints table and zombie's current waypoint
local waypoints
local currentWaypointIndex
local function followPath()
if destination and destination.Character then
-- Compute and check the path
path:ComputeAsync(zombie.HumanoidRootPart.Position, destination.Character.HumanoidRootPart.Position)
-- Empty waypoints table after each new path computation
waypoints = {}
if path.Status == Enum.PathStatus.Success then
-- Get the path waypoints and start zombie walking
waypoints = path:GetWaypoints()
-- Move to first waypoint
local index = 0
for i,v in pairs(waypoints) do
local closest = nil
index = index + 1
if closest == nil or (zombie.HumanoidRootPart.Position - v.Position).Magnitude < closest then
closest = (zombie.HumanoidRootPart.Position - v.Position).Magnitude
currentWaypointIndex = index
end
end
index = 0
if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
print("trying to jump")
else
humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
end
else
print("path not available")
followPath()
end
end
end
local function onWaypointReached(reached)
if reached and currentWaypointIndex < #waypoints then
currentWaypointIndex = currentWaypointIndex + 1
local before = currentWaypointIndex
if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
print("trying to jump")
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
else
humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
wait(4)
if before == currentWaypointIndex then
followPath()
end
end
end
end
local function onPathBlocked(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex > currentWaypointIndex then
print("Recalculating")
-- Call function to re-compute the path
destination = GrabTarget()
followPath()
end
end
local function UpdatePath()
if destination and destination.Character then
local HRP = destination.Character.HumanoidRootPart
local newtarget = GrabTarget()
local currentpos = Vector3.new(math.round(HRP.Position.X*10^(2)/10^(2)),math.round(HRP.Position.Y*10^(2)/10^(2)),math.round(HRP.Position.Z*10^(2)/10^(2)))
destination = newtarget
if destination ~= lastknowntarget or lastknownpos ~= currentpos then
lastknowntarget = destination
lastknownpos = currentpos
followPath()
print("Following")
end
else
destination = GrabTarget()
end
end
-- Connect 'Blocked' event to the 'onPathBlocked' function
path.Blocked:Connect(onPathBlocked)
-- Connect 'MoveToFinished' event to the 'onWaypointReached' function
humanoid.MoveToFinished:Connect(onWaypointReached)
runservice.Heartbeat:Connect(UpdatePath)
followPath(destination)
NEW
local pathfindingservice = game:GetService("PathfindingService")
local runservice = game:GetService("RunService")
local zombie = script.Parent
local human = zombie.Humanoid
local path = pathfindingservice:CreatePath()
local currentwaypoint
local waypoints
local lastknownpos
local lastknowntarget
zombie.PrimaryPart:SetNetworkOwner(nil)
local function GrabTarget()
local players = game.Players:GetChildren()
local closest
local target
for i,v in pairs(players) do
local char = v.Character or v.CharacterAdded:Wait()
local HRP = char.HumanoidRootPart
local distance = (HRP.Position - zombie.HumanoidRootPart.Position).Magnitude
distance = math.round(distance*10^(3))/10^(3)
if not closest or distance < closest then
target = char
closest = distance
end
end
closest = nil
return target
end
local function InitiateTarget(target)
path:ComputeAsync(zombie.HumanoidRootPart.Position,target.HumanoidRootPart.Position)
waypoints = {}
local index = 0
local closest
if path.Status == Enum.PathStatus.Success then
currentwaypoint = 1
waypoints = path:GetWaypoints()
for i,v in ipairs(waypoints) do
index = index + 1
local dist = (zombie.HumanoidRootPart.Position - v.Position).Magnitude
if not closest or dist < closest then
closest = dist
currentwaypoint = index
end
end
closest = nil
if waypoints[currentwaypoint].Action == Enum.PathWaypointAction.Jump then
print("Jumping")
human:ChangeState(Enum.HumanoidStateType.Jumping)
else
print("Walking")
human:MoveTo(waypoints[currentwaypoint].Position)
end
else
InitiateTarget(GrabTarget())
end
end
local function Update()
local target = GrabTarget()
if target then
local targetpos = target.HumanoidRootPart.Position
local finalpos = Vector3.new(math.round(targetpos.X*10^(3))/10^(3),math.round(targetpos.Y*10^(3))/10^(3),math.round(targetpos.Z*10^(3))/10^(3))
if target ~= lastknowntarget or finalpos ~= lastknownpos then
print("Recalculating")
lastknownpos = finalpos
lastknowntarget = target
InitiateTarget(target)
end
end
end
local function FollowThrough(reached)
if reached and currentwaypoint < #waypoints then
currentwaypoint = currentwaypoint + 1
if waypoints[currentwaypoint].Action == Enum.PathWaypointAction.Jump then
print("Jumping")
human:ChangeState(Enum.HumanoidStateType.Jumping)
else
human:MoveTo(waypoints[currentwaypoint].Position)
end
elseif not reached then
Update()
end
end
human.MoveToFinished:Connect(FollowThrough)
runservice.Heartbeat:Connect(Update)
EXAMPLE