I’ve got a boundary condition where MultiTargetPath has a chosen index that is NOT the shortest path - when calculating using pathsForAll = true, it returns all paths with a shorter length for the path NOT selected than for the path it selected.
Reproduction verified on v5.3.8:
- Using
RichAIon aRecastGraph - Using
FunnelModifierto simplify the calculated paths - Very specific agent & target placements (see screenshot)
It appears to be selecting a path based on the node-to-node path, before applying path modifiers.
(Understandable, because we want to stop calculating once we’ve found the shortest path!)
… but it DOES still apply modifiers to the returned path, giving a very unexpected result where it appears that it can’t measure the path length properly.
See this screenshot for setup positioning:
- Guy with the white shirt, upper centre is the pathfinding agent. He began near the green cross.
- Starting near the corner of a large triangle on the navmesh, with a nearby target that’s also near the corner of the large triangle (guy with blue hoodie, lower left corner), and a further away target that is NEARER to the centre of the large triangle than the correct target (woman, lower right corner)
- The calculated paths, without modifiers, go to the centre of the large triangle (approx. where the second green X is) and then to the target destinations. The correct path has a few extra steps through those long thin triangles, but the remaining path is approx. straight.
- Calculated path to the wrong target, drawn in blue, is shorter than the correct path because the woman is standing nearer that first waypoint at the node position.
- Correct path, drawn in yellow, is longer because of the additional zig-zagging.
- If the correct path is selected the NPC will still walk to that target via a shorter path (even without modifiers) because of turning towards the next waypoint before reaching the current waypoint.
- If a funnel modifier is added to the seeker, it returns two straight-line paths to each target but selects the longer path.
- The red line drawn by a Gizmo is my selected path after I used my workaround to manually chose the shorter of the two returned paths. It is already a straight line because of the FunnelModifier.
My current workaround is to return all paths & not trust the selected path. I then check the length of each path & update the returned MultiTargetPath’s chosenTarget, path & vectorPath.
Potential fixes:
-It’s understandable why it doesn’t apply the modifiers, because how can it if we want to stop after finding the first/shortest path - calculating all paths to do this check would lose the benefit of doing it all in one query…but I couldn’t see anything in the documentation mentioning this boundary condition or warning it could happen.
- Applying filters before selecting the path when pathsForAll is true would be bad if it returns a different path to when only requesting the shortest path. Swapping one inconsistency for another.
When pathsForAll is false, would it be possible to continue searching for paths for some minimum distance or pathlength percentage? e.g. after finding a path of whatever length, continue searching for paths until you’ve checked for anything 1.5x the path length?
Then once you have the paths, whether or not pathsForAll is true or false, apply the filters first and then check for the shortest path.
This should give a result that:
- Gives consistent results for the best path whether searching for one or multiple paths
- Limits the amount of searching if there’s one clearly shortest path
- Selects based on the same path that gets returned to the user (so results will match the agent’s path)
If this isn’t considered a bug, or not worth fixing or otherwise a problem - please put a warning check in the code or update the documentation.
We really need at least a warning because it creates what seems like an intermittent bug.
Because of the specific agent/target placement & the variability of recast graphs nodes (which are invisible in the game view), it’s hard to replicate this in builds.
It causes a lot of frustration for the QA & Dev team because they’d test & think that it was working due to slightly different placement.
Hopefully this helped!
I haven’t categorized this for RecastGraph because I’m not sure if similar conditions can happen on other graph types.
Cheers,
Tony
