Download

Is it possible to change how navmesh pathfinding behaves?

Hi,

so I am trying to implement path finding for my top down tank shooter game. Since UE4 framework was mostly implemented with just characters in mind, I can not use majority if framework features, such as AI move commands, as they just move actor in a straight line, which is clearly not how for example a Tank moves, as it first needs to steer towards the direction and only then move.

So I have a custom AI controller which commands the tank using a tank driving interface, having controls for throttle and steering. What I am using from the UE4’s framework is navmesh and path finding, but I seem to have issues with that as well. The “Find Path to Location Synchronously” function seems to generate somewhat concave paths, which make something like a driving tank with some weight, acceleration and limited steering radius get stuck all the time. What helped a bit was to create a custom navmesh agent with proportions closer matching to the tank dimensions, but it’s still not enough.

Basically, this is how it looks now:

When the tank reaches certain distance from a “Find Path to Location Synchronously” generated waypoint, I iterate to a next waypoint. I also tried to add some code so that the tank slows down as it approaches each waypoint so it has more time to slow down and make more sharp turn, but it areas with lots of turns, it has made the tank way too slow. Sometimes, around very thin walls, the tank can get stuck by triggering all the points around the end of the wall, and then turn towards the last one and start driving into a wall instead of going around.

So, my question is if there is any way I can actually affect the way “Find Path to Location Synchronously” generates the waypoints, sort of like this:


The red line is the line that the function actually generates. it’s way too dense, detailed and concave. I was wondering if I could get a simpler, more convex set of waypoints that doesn’t adhere to outline of the navmesh so closely.

There are two things I think can impact this, but I have been unable to utilize them as the documentation for navmesh related stuff is really poor:

1, “Find Path to Location Synchronously” contains a “Pathfinding context” pin, which is supposed to affect the parameters of the generated path. I find it super confusing, as it says it takes either NavigationData, Pawn or Controller. All these 3 are super different classes, so I can’t imagine what they could have in common that could be used to affect the plotted path. I mean I’d assume for example when plugging in a Pawn, it’d use a bounding box to increase offset from the edges of navmesh, but then if I plugged a controller there, that one usually doesn’t have any physical representation, so it probably won’t be doing that.

2, Navmesh Agent setting contain Vector3 set of values for something called “Default Query Extent”. I believe it is something that has to do with the way paths and navmesh are generated, but there is no documentation for what it does whatsoever :frowning:

So TL;DR - Is there a way to somehow affect how UE4 pathfinding works and repurpose it for the use with vehicles, or will I have to implement a pathfinding of my own?

Thank you in advance.

So I take it the answer is no? :slight_smile:

I know this I really late and I’m kind of a newbie, but I’m making a similar system right now and ran into similar issues. I’m still currently working through it but something I tried was calculating the path first with the find location asynchronous then fed that into a loop that checked if the point before and after my current index was withing so many units of my current index. If it was then I marked it for deletion and then reconstructed the array with the points left. Thereby smoothing the path based on the distance amount.

Late Answer:
You can use FNavMeshPath::OffsetFromCorners for this. But it is now available in blueprints.

There is an example in ANavigationTestingActor::SearchPathTo function.


FPathFindingResult Result = NavSys->FindPathSync(NavAgentProps, Query, Mode);

    const double EndTime = FPlatformTime::Seconds();
    const float Duration = (EndTime - StartTime);
    PathfindingTime = Duration * 1000000.0f;            // in micro seconds [us]
    bPathIsPartial = Result.IsPartial();
    bPathExist = Result.IsSuccessful();
    bPathSearchOutOfNodes = bPathExist ? Result.Path->DidSearchReachedLimit() : false;
    LastPath = Result.Path;
    PathCost = bPathExist ? Result.Path->GetCost() : 0.0f;

    if (bPathExist)
    {
        LastPath->AddObserver(PathObserver);

** if (OffsetFromCornersDistance > 0.0f)
        {
            ((FNavMeshPath*)LastPath.Get())->OffsetFromCorners(OffsetFromCornersDistance);
        }**
    }

You can also find variable **bUseBetterOffsetsFromCorners (**use it by changing BaseEngine.ini) - but i don’t know what it does exacly.


/** TODO: switch to disable new code from OffsetFromCorners if necessary - remove it later */
    UPROPERTY(config)
    uint32 bUseBetterOffsetsFromCorners : 1;


But 2 warnings:

  1. It’s not cheap (you can use STAT_Navigation to see how exepnsive it is)
  2. In 4.17 (i was using it then) version there was a bug - not sure if it’s fixed. In 99.9% OffsetFromCorners worked as expected but in very rare occasions when there was long path to change, after using this function the path was broken - it could lead pawn in areas without navmesh.

Thanks…

I’ve learned a lot more since I posted it. It looks like default offset is generated from the navmesh agent data, specifically navmesh agent radius. So it’s mainly a matter of correctly setting up navmesh agent types for navmesh generation and then making sure actual navmesh agent proportions are correctly established (they are often generated from bounding cylinder). The main issue is lack of the documentation about the whole navmesh system, leaving user to piece all that puzzle together.