Download

Is Point a Navmash

I’m new in C++ and Unreal4. I try to find out if a point is reachable via the Navmash or not.
I’m generating random points in an Area for an Ai. But maybe the point is on a tree or in water….

Sadly I can’t find a tutorial or documentation how the NavigationSystem, NavigationGraph, NavigationComponent, … working together. So I start to stealing code snippets from the API. I know the hole Behavior Tree is still in experimental but maybe you can recommend something.

I try to use [FONT=Courier New]TestPathSync(https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/AI/Navigation/UNavigationSystem/TestPathSync/index.html)
But I can’t get the Parameter Right. Here is some code, I currently playing with but I seems like everything is messed up.


bool AGregariousAnimalController::IsPointOnNavMesh(FVector start, FVector target){
	AAIController* Ai = static_cast<AAIController*>(this);
	UNavigationSystem* NavSys = GetWorld()->GetNavigationSystem();
	UObject* Owner = StaticCast<UObject*>(this);
	ANavigationGraph* NavGraph = GetWorld()->SpawnActor<ANavigationGraph>();
	ANavigationData* NavData = StaticCast<ANavigationData*>(NavGraph);
	class ANavigationData* NavDataClass = NavData;

	TSubclassOf<UNavigationQueryFilter> FilterClass;
	TSharedPtr<const FNavigationQueryFilter, ESPMode::NotThreadSafe> queryFilter = UNavigationQueryFilter::GetQueryFilter(Ai, FilterClass);
	FPathFindingQuery Query = {};
	Query.NavData = NavDataClass;
	Query.StartLocation = start;
	Query.EndLocation = target;
	Query.QueryFilter = queryFilter;//NavGraph->GetDefaultQueryFilter();


	//FPathFindingQuery query = { Owner, NavDataClass, start, target, NavData->GetDefaultQueryFilter()};
	return NavSys->TestPathSync(Query, EPathFindingMode::Regular);
	//return false;
}

Now I getting an access violation error at runtime when I try to call GetNavigationSystem?
But also [FONT=Courier New]SpawnActor<ANavigationGraph>() does not feel right too. (But I can store this in a class variable)
[FONT=Courier New]class ANavigationData* NavDataClass = NavData; also does not look right.
And how can I get an Instance to a filter class?

greetings from Germany

Hi,

i had kind of similar problems, when doing point&click movement; I wanted to detect if any point i clicked on is outside of the NavMesh and if so, i wanted the character to go straight into that direction instead of NavMesh Navigation.
I couldnt find any method like “IsPointOnNavmesh” or something similar, so i utilized the existing components for finding a path and checking if its a valid one.

You may be able to incorporate something like that:

In your PlayerController .h file, add a NavComponent and a PathFollowingComponent:



private:
/** Component used for pathfinding and querying environment's navigation. */
UPROPERTY()
TSubobjectPtr<class UNavigationComponent> NavComponent;
 
/** Component used for moving along a path. */
UPROPERTY()
TSubobjectPtr<class UPathFollowingComponent> PathFollowingComponent;


Then we need to initialize them on instantiation of the controller, so in your constructor-method of your .cpp you need to call them.


 
    // set up navigation component
    NavComponent = PCIP.CreateDefaultSubobject<UNavigationComponent>(this, TEXT("NavComponent"));
 
    PathFollowingComponent = PCIP.CreateDefaultSubobject<UPathFollowingComponent>(this, TEXT("PathFollowingComponent"));


Then, something like the following method should work for you.
We do not exactly check here if the Point is on the NavMesh, but if the NavigationComponent can actually find a Path to the given destination.



bool AMyPlayerController::IsPointOnNavMesh(FVector* dest) {
    bool bFoundPath = NavComponent->FindPathToLocation(dest, NULL);
    if (bFoundPath == false || NavComponent->GetPath().IsValid() == false) {
      // Point is not on NavMesh or not reachable for some other reason
      return false;
    }
    return true;
}


Hope that helps somehow,
Cheers,
Indy

Thanks! You are my hero! That is exactly what I’m looking for!
I simply run in the wrong direction.

But, is there a tutorial for path finding? :rolleyes:

Hi,

generally there is no need for a Tutorial with basic pathfinding, since it is quite easy to implement, given there are no such special cases like checking if a point is on a navmesh and stuff :slight_smile:

Normally, you use different methods for navigating your playercharacter than you would do with your AI; Though, if you already implemented the 2 components as shown above in your PlayerController (Please note that these are already there for AIControllers!), you can generally use the following:



if (IsPointOnNavMesh(dest)) {
    PathFollowComp->RequestMove(NavComponent->GetPath(), NULL, 100.0f);
}


And thats it, now your Characters will follow paths all along.

Btw, i dont know how you generate your random points but….



    const float searchRadius = 500.0f;
    FNavLocation randomDest;		
    const bool foundPoint = NavSys->GetRandomPointInRadius(GetPawn()->GetActorLocation(), searchRadius, randomDest);
    if (foundPoint) {
        NavComponent->FindPathToLocation(randomDest, NULL);
        PathFollowComp->RequestMove(NavComponent->GetPath(), NULL, 100.0f);
    }


And for checking if the AI has reached the destination point, just override OnMoveCompleted in your AIController (This event is not there for playercontrollers i think):



void MyAIController::OnMoveCompleted(uint32 RequestID, EPathFollowingResult::Type Result) {
        if (Result == EPathFollowingResult::Success) {
                // Get the next point for movement, or play an animation for the ai cause its happy it reached the destination…
                ...
        }
}


Cheers,
Indy