Right now I am trying to get an AI character to pathfind around my map, but currently he gets stuck on simple geometry.
I believe this is because when his agent radius is large, he believes he is stuck inside the geometry and can’t pathfind. However, when it is smaller, he gets caught on corners and cuts them tightly to where it looks unnatural. Ideally I would have a large agent radius but have him avoid stuck he’s trapped when creating a path.
This issue has been haunting me since the beginning of the development of my game, and fiddling with Roblox’s abstracted pathfinding implementation has been annoying.
Here’s some footage:
local pathParams = {
AgentHeight = 14.4,
--AgentRadius = 3.3, --Actual size of mario's cylindrical collision hull
AgentRadius = 4,
AgentCanJump = false,
AgentCanClimb = false,
}
...
--Mario paths to a given position. Returns success or fail.
function pathToPosition(targetPos:Vector3, ignoreHearing:boolean, ignoreVision:boolean): boolean
marioParts.humanoid:MoveTo(marioParts.humanoidRootPart.Position)
local path = game:GetService("PathfindingService"):CreatePath(pathParams)
path:ComputeAsync(PelvisPosFromCenter(), targetPos)
--Failed path generation.
if path.Status == Enum.PathStatus.NoPath then
warn("Mario: Failed to generate path to point:", targetPos, "----------")
if visualizeWP then
rayVisual(marioParts.CollisionHull.Position, targetPos, true)
drawWaypoints({marioParts.CollisionHull})
end
getUnstuck()
resetMovesounds()
return false
end
--Path success
local waypoints = path:GetWaypoints()
if visualizeWP then drawWaypoints(waypoints) end
for i, waypoint in ipairs(waypoints) do
--Skip last 2 waypoints to stop mario getting stuck
if i > #waypoints - 2 then
break;
end
--Jump if waypoint calls for it
if waypoint.Action == Enum.PathWaypointAction.Jump then
marioParts.humanoid.Jump = true
end
--Move to waypoint
marioParts.humanoid:MoveTo(waypoint.Position)
if (marioParts.CollisionHull.Position - waypoint.Position).magnitude > 30 then
print("mgro: I have strayed too far from the path")
break
end
local timeOut = marioParts.humanoid.MoveToFinished:Wait()
if not timeOut then
getUnstuck()
break
end
local seenHuman: Humanoid? = findClosestVisiblePlayer()
if seenHuman and not ignoreVision then
task.wait(0.4)
seenHuman = findClosestVisiblePlayer()
if seenHuman then
print("mgro: Human seen! Exiting path")
resetAnimations(false, true, false)
return true
end
end
if checkHearing() and not ignoreHearing then
print("mgro: Heard!")
resetAnimations(false, false, false)
return true
end
end
return true
end