Attached below are a few screenshots containing the navigation mesh of a maze as well as where path.Blocked is firing, (20x20 maze from this post)
The white block represents where Path.Blocked is firing, it seems to be firing as the AI needs to jump down to that position. This causes unintended behavior by my NPC. One possible workaround I have found is I can instead include a sort of ramp so it does not have to jump down (I applied this solution so the NPC could go up stairs as blocked would fire similarly for stairs).
Similar path.Blocked misfiring behavior happens when the AI is required to jump over a simple blockaid, but I have no possible workarounds to this that do not involve placing ramps.
After a bit of testing also, I have found that the ramp has to be gently sloping in order for this fix to work properly. Steep ramps will not work properly.
These are all solutions that can be applied through map design, but are there any alternative fixes you have applied or that I could experiment with?
Fall example
Fall example fix
Stairs example
Potential fix for the stairs
Ramp Example
Code for the NPC
local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = true,
WaypointSpacing = 5,
Costs = {
Water = 20
}
})
local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = workspace.Destination
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local unblockedConnection
local function followPath(destination)
-- Compute the path
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
humanoid:MoveTo(humanoid.RootPart.Position)
if success and path.Status == Enum.PathStatus.Success then
-- Get the path waypoints
waypoints = path:GetWaypoints()
if blockedConnection then
blockedConnection:Disconnect()
blockedConnection = nil
end
if reachedConnection then
reachedConnection:Disconnect()
reachedConnection = nil
end
if unblockedConnection then
unblockedConnection:Disconnect()
unblockedConnection = nil
end
humanoid:MoveTo(humanoid.RootPart.Position)
-- Detect if path becomes blocked
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Check if the obstacle is further down the path
--[[print("BLOCKED")
local PartInstance = Instance.new("Part")
PartInstance.Size = Vector3.new(1,1,1)
PartInstance.Material = Enum.Material.Neon
PartInstance.Color = Color3.fromRGB(255,255,255)
PartInstance.Anchored = true
PartInstance.Position = waypoints[blockedWaypointIndex].Position
PartInstance.CanCollide = false
PartInstance.Name = "BLOCKEDPOS"
PartInstance.Parent = workspace]]
if blockedWaypointIndex >= nextWaypointIndex then
--print("Blocked ahead of us")
-- Stop detecting path blockage until path is re-computed
reachedConnection:Disconnect()
reachedConnection = nil
blockedConnection:Disconnect()
humanoid:MoveTo(humanoid.RootPart.Position)
-- Call function to re-compute new path
followPath(destination)
end
end)
--[[unblockedConnection = path.Unblocked:Connect(function(unblockedWaypointIndex)
print("path unblocked at ".. unblockedWaypointIndex)
end)]]
-- Detect when movement to next waypoint is complete
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Increase waypoint index and move to next waypoints
nextWaypointIndex += 1
if waypoints[nextWaypointIndex].Action == Enum.PathWaypointAction.Jump and humanoid:GetState() ~= Enum.HumanoidStateType.Jumping then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
reachedConnection = nil
humanoid:MoveTo(humanoid.RootPart.Position)
if blockedConnection then
blockedConnection:Disconnect()
end
if unblockedConnection then
unblockedConnection:Disconnect()
end
end
end)
end
-- Initially move to second waypoint (first waypoint is path start; skip it)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
script.Parent.Humanoid.RootPart:SetNetworkOwner(nil)
while true do
task.wait(4)
followPath(TEST_DESTINATION.Position)
end
Character also does tend to get stuck on the blocked waypoint