FAIRequestID AAIController::RequestPathAndMove(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query) { FAIRequestID RequestID; UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); if (NavSys) { FPathFindingResult PathResult = NavSys->FindPathSync(Query); if (PathResult.Result != ENavigationQueryResult::Error) { if (PathResult.IsSuccessful() && PathResult.Path.IsValid()) { if (MoveRequest.IsUsingPathfinding()) { if (MoveRequest.HasGoalActor()) { PathResult.Path->SetGoalActorObservation(*MoveRequest.GetGoalActor(), 100.0f); } PathResult.Path->EnableRecalculationOnInvalidation(true); } RequestID = RequestMove(MoveRequest, PathResult.Path); } } else { UE_VLOG(this, LogAINavigation, Error, TEXT("Trying to find path to %s resulted in Error"), *GetNameSafe(MoveRequest.GetGoalActor())); } } return RequestID; }
void AAIController::FindPathForMoveRequest(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query, FNavPathSharedPtr& OutPath) const { SCOPE_CYCLE_COUNTER(STAT_AI_Overall); UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); if (NavSys) { FPathFindingResult PathResult = NavSys->FindPathSync(Query); if (PathResult.Result != ENavigationQueryResult::Error) { if (PathResult.IsSuccessful() && PathResult.Path.IsValid()) { if (MoveRequest.IsMoveToActorRequest()) { PathResult.Path->SetGoalActorObservation(*MoveRequest.GetGoalActor(), 100.0f); } PathResult.Path->EnableRecalculationOnInvalidation(true); OutPath = PathResult.Path; } } else { UE_VLOG(this, LogAINavigation, Error, TEXT("Trying to find path to %s resulted in Error") , MoveRequest.IsMoveToActorRequest() ? *GetNameSafe(MoveRequest.GetGoalActor()) : *MoveRequest.GetGoalLocation().ToString()); UE_VLOG_SEGMENT(this, LogAINavigation, Error, GetPawn() ? GetPawn()->GetActorLocation() : FAISystem::InvalidLocation , MoveRequest.GetGoalLocation(), FColor::Red, TEXT("Failed move to %s"), *GetNameSafe(MoveRequest.GetGoalActor())); } } }
FAIRequestID AAIController::RequestPathAndMove(FPathFindingQuery& Query, AActor* Goal, float AcceptanceRadius, bool bStopOnOverlap, FCustomMoveSharedPtr CustomData) { FAIRequestID RequestID; UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); if (NavSys) { FPathFindingResult PathResult = NavSys->FindPathSync(Query); if (PathResult.Result != ENavigationQueryResult::Error) { if (PathResult.IsSuccessful() && PathResult.Path.IsValid()) { if (Goal) { PathResult.Path->SetGoalActorObservation(*Goal, 100.0f); } PathResult.Path->EnableRecalculationOnInvalidation(true); } RequestID = RequestMove(PathResult.Path, Goal, AcceptanceRadius, bStopOnOverlap, CustomData); } else { UE_VLOG(this, LogBehaviorTree, Error, TEXT("Trying to find path to %s resulted in Error"), *GetNameSafe(Goal)); } } return RequestID; }
void ANavigationTestingActor::SearchPathTo(ANavigationTestingActor* Goal) { #if WITH_EDITORONLY_DATA if (EdRenderComp) { EdRenderComp->MarkRenderStateDirty(); } #endif // WITH_EDITORONLY_DATA if (Goal == NULL) { return; } UNavigationSystem* NavSys = GetWorld()->GetNavigationSystem(); check(NavSys); const double StartTime = FPlatformTime::Seconds(); FPathFindingQuery Query = BuildPathFindingQuery(Goal); EPathFindingMode::Type Mode = bUseHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular; 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); } } #if WITH_RECAST && WITH_EDITORONLY_DATA if (bGatherDetailedInfo && !bUseHierarchicalPathfinding) { ARecastNavMesh* RecastNavMesh = Cast<ARecastNavMesh>(MyNavData); if (RecastNavMesh && RecastNavMesh->HasValidNavmesh()) { PathfindingSteps = RecastNavMesh->DebugPathfinding(Query, DebugSteps); } } #endif }
void UNavigationComponent::OnSmartLinkBroadcast(class USmartNavLinkComponent* NearbyLink) { // update only when agent is actually moving if (NearbyLink == NULL || !Path.IsValid() || PathFollowComp == NULL || PathFollowComp->GetStatus() == EPathFollowingStatus::Idle) { return; } UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); if (NavSys == NULL || MyNavAgent == NULL || GetNavData() == NULL) { return; } const bool bHasLink = Path->ContainsSmartLink(NearbyLink); const bool bIsEnabled = NearbyLink->IsEnabled(); if (bIsEnabled == bHasLink) { // enabled link, path already use it - or - disabled link and path it's not using it return; } const FVector GoalLocation = Path->PathPoints.Last().Location; FPathFindingResult Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), FPathFindingQuery(GetNavData(), MyNavAgent->GetNavAgentLocation(), GoalLocation, StoredQueryFilter), bDoHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular); if (Result.IsSuccessful() || Result.IsPartial()) { const bool bNewHasLink = Result.Path->ContainsSmartLink(NearbyLink); if ((bIsEnabled && !bHasLink && bNewHasLink) || (!bIsEnabled && bHasLink && !bNewHasLink)) { SetPath(Result.Path); NotifyPathUpdate(); } } }
bool UNavigationComponent::GeneratePathTo(const FVector& GoalLocation, TSharedPtr<const FNavigationQueryFilter> QueryFilter) { if (GetWorld() == NULL || GetWorld()->GetNavigationSystem() == NULL || GetOuter() == NULL) { return false; } // Make sure we're trying to path to the closest valid location TO that location rather than the absolute location. // After talking with Steve P., if we need to ever allow pathing WITHOUT projecting to nav-mesh, it will probably be // best to do so using a flag while keeping this as the default behavior. NOTE:` If any changes to this behavior // are made, you should search for other places in UNavigationComponent using NavMeshGoalLocation and make sure the // behavior remains consistent. // make sure that nav data is updated GetNavData(); const FNavAgentProperties* NavAgentProps = MyNavAgent ? MyNavAgent->GetNavAgentProperties() : NULL; if (NavAgentProps != NULL) { FVector NavMeshGoalLocation; #if ENABLE_VISUAL_LOG UE_VLOG_LOCATION(GetOwner(), GoalLocation, 34, FColor(0,127,14), TEXT("GoalLocation")); const FVector ProjectionExtent = MyNavData ? MyNavData->GetDefaultQueryExtent() : FVector(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL); UE_VLOG_BOX(GetOwner(), FBox(GoalLocation - ProjectionExtent, GoalLocation + ProjectionExtent), FColor::Green, TEXT_EMPTY); #endif if (ProjectPointToNavigation(GoalLocation, NavMeshGoalLocation) == QuerySuccess) { UE_VLOG_SEGMENT(GetOwner(), GoalLocation, NavMeshGoalLocation, FColor::Blue, TEXT_EMPTY); UE_VLOG_LOCATION(GetOwner(), NavMeshGoalLocation, 34, FColor::Blue, TEXT_EMPTY); UNavigationSystem* NavSys = GetWorld()->GetNavigationSystem(); FPathFindingQuery Query(MyNavData, MyNavAgent->GetNavAgentLocation(), NavMeshGoalLocation, QueryFilter); const EPathFindingMode::Type Mode = bDoHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular; FPathFindingResult Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode); // try reversing direction if (bSearchFromGoalWhenOutOfNodes && !bDoHierarchicalPathfinding && Result.Path.IsValid() && Result.Path->DidSearchReachedLimit()) { // quick check if path exists bool bPathExists = false; { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: HPA* test time"), STAT_Navigation_PathVerifyTime, STATGROUP_Navigation); bPathExists = NavSys->TestPathSync(Query, EPathFindingMode::Hierarchical); } UE_VLOG(GetOwner(), LogNavigation, Log, TEXT("GeneratePathTo: out of nodes, HPA* path: %s"), bPathExists ? TEXT("exists, trying reversed search") : TEXT("doesn't exist")); // reverse search if (bPathExists) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: reversed test time"), STAT_Navigation_PathReverseTime, STATGROUP_Navigation); TSharedPtr<FNavigationQueryFilter> Filter = QueryFilter.IsValid() ? QueryFilter->GetCopy() : MyNavData->GetDefaultQueryFilter()->GetCopy(); Filter->SetBacktrackingEnabled(true); FPathFindingQuery ReversedQuery(MyNavData, Query.EndLocation, Query.StartLocation, Filter); Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode); } } if (Result.IsSuccessful() || Result.IsPartial()) { CurrentGoal = NavMeshGoalLocation; SetPath(Result.Path); if (IsFollowing() == true) { // make sure ticking is enabled (and it shouldn't be enabled before _first_ async path finding) SetComponentTickEnabledAsync(true); } NotifyPathUpdate(); return true; } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Failed to generate path to destination")); } } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Destination not on navmesh (and nowhere near!)")); } } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("UNavigationComponent::GeneratePathTo: NavAgentProps == NULL (Probably Pawn died)")); } return false; }