Currently, I’m making a pathfinding AI script however sometimes it doesn’t jump when it needs to to get to the destination, resulting in it getting stuck in a wall.
Video:
local PathfindingService = game:GetService("PathfindingService")
local RootPart = script.Parent:WaitForChild("HumanoidRootPart")
local Humanoid = script.Parent.Humanoid
local Path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentCanClimb = false
})
Path:ComputeAsync(RootPart.Position, workspace.Part.Position)
-- Visualize waypoints
for _, Waypoint in pairs(Path:GetWaypoints()) do
local Visualizer = Instance.new("Part")
Visualizer.Anchored = true
Visualizer.Material = Enum.Material.Neon
Visualizer.Size = Vector3.new(1, 1, 1)
Visualizer.Shape = Enum.PartType.Ball
Visualizer.Position = Waypoint.Position
Visualizer.CanCollide = false
Visualizer.CanQuery = false
Visualizer.CanTouch = false
Visualizer.Parent = workspace
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Visualizer.Color = Color3.fromRGB(255, 0, 0)
end
end
-- Move to waypoints
for _, Waypoint in pairs(Path:GetWaypoints()) do
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
Humanoid:MoveTo(Waypoint.Position)
local Timeout = Humanoid.MoveToFinished:Wait(1)
if not Timeout then
Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
First I’d try making a Path.Blocked function when the path is made, and then change the humanoid state like you do in the waypoint action condition. It’s also worth a shot manually checking for obstacles with SpacialQuery or Raycasting. I would also tweak that last bit in the waypoints iteration, since it seems to only check if the next point has been reached within 1 second and if not it jumps, which is too strict of a condition and too vague of a solution to be viable when needed.
I’ve changed my code to match the one in the pathfinding documentation and also added raycasting to check whether there were obstacles between the waypoints, however, the AI now suddenly stops after moving past around ~3 waypoints. (Without the raycast thing, the behaviour of the AI continuing to walk into walls continues like nothing ever happened.)
Code:
local PathfindingService = game:GetService("PathfindingService")
local RootPart = script.Parent:WaitForChild("HumanoidRootPart")
local Humanoid = script.Parent.Humanoid
local Path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentCanClimb = false,
})
local BlockedConnection = nil
local ReachedConnection = nil
local NextWaypointIndex = 2
local WaypointVisualizers = {}
local WaypointBlockedCastParams = RaycastParams.new()
WaypointBlockedCastParams.FilterType = Enum.RaycastFilterType.Exclude
WaypointBlockedCastParams.FilterDescendantsInstances = {script.Parent}
local function MoveToPart()
local Success, Error = pcall(function()
Path:ComputeAsync(RootPart.Position, workspace.Part.Position)
end)
if Success and Path.Status == Enum.PathStatus.Success then
for _, WaypointVisualizer in pairs(WaypointVisualizers) do
WaypointVisualizer:Destroy()
end
local Waypoints = Path:GetWaypoints()
-- Visualize waypoints
for _, Waypoint in pairs(Waypoints) do
local Visualizer = Instance.new("Part")
Visualizer.Anchored = true
Visualizer.Material = Enum.Material.Neon
Visualizer.Size = Vector3.new(1, 1, 1)
Visualizer.Shape = Enum.PartType.Ball
Visualizer.Position = Waypoint.Position
Visualizer.CanCollide = false
Visualizer.CanQuery = false
Visualizer.CanTouch = false
Visualizer.Parent = workspace
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Visualizer.Color = Color3.fromRGB(255, 0, 0)
end
end
-- Move to waypoints
BlockedConnection = Path.Blocked:Connect(function(BlockedWaypointIndex)
if BlockedWaypointIndex >= NextWaypointIndex then
BlockedConnection:Disconnect()
MoveToPart()
end
end)
if not ReachedConnection then
ReachedConnection = Humanoid.MoveToFinished:Connect(function(Reached)
if Reached and NextWaypointIndex < #Waypoints then
NextWaypointIndex += 1
if Waypoints[NextWaypointIndex].Action == Enum.PathWaypointAction.Jump then
Humanoid.Jump = true
end
local Direction = (Waypoints[NextWaypointIndex].Position - RootPart.Position)
local IsNextWaypointBlocked = workspace:Raycast(RootPart.Position, Direction * Direction.Magnitude, WaypointBlockedCastParams)
if IsNextWaypointBlocked then
ReachedConnection:Disconnect()
BlockedConnection:Disconnect()
MoveToPart()
return
end
Humanoid:MoveTo(Waypoints[NextWaypointIndex].Position)
else
ReachedConnection:Disconnect()
BlockedConnection:Disconnect()
end
end)
end
NextWaypointIndex = 2
Humanoid:MoveTo(Waypoints[NextWaypointIndex].Position)
end
end
MoveToPart()
Based on your first video, it looks like the PathfindingService doesn’t count that point as a jump (there is no red waypoint there), meaning that you might need to increase the difference in height between the steps, or reduce it so the humanoid can climb without jumping.
You can also turn on navigation mesh in studio settings to see how the engine computes information such as where a jump is needed.
I recommend checking the velocity of the NPC’s humanoidrootpart every so often, and making them jump if its magnitude is near to zero, as this could indicate the NPC is stuck.