void UEnvQueryGenerator_SimpleGrid::GenerateItems(FEnvQueryInstance& QueryInstance) const { UObject* BindOwner = QueryInstance.Owner.Get(); GridSize.BindData(BindOwner, QueryInstance.QueryID); SpaceBetween.BindData(BindOwner, QueryInstance.QueryID); float RadiusValue = GridSize.GetValue(); float DensityValue = SpaceBetween.GetValue(); const int32 ItemCount = FPlatformMath::TruncToInt((RadiusValue * 2.0f / DensityValue) + 1); const int32 ItemCountHalf = ItemCount / 2; TArray<FVector> ContextLocations; QueryInstance.PrepareContext(GenerateAround, ContextLocations); TArray<FNavLocation> GridPoints; GridPoints.Reserve(ItemCount * ItemCount * ContextLocations.Num()); for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { for (int32 IndexX = 0; IndexX <= ItemCount; ++IndexX) { for (int32 IndexY = 0; IndexY <= ItemCount; ++IndexY) { const FNavLocation TestPoint = FNavLocation(ContextLocations[ContextIndex] - FVector(DensityValue * (IndexX - ItemCountHalf), DensityValue * (IndexY - ItemCountHalf), 0)); GridPoints.Add(TestPoint); } } } ProjectAndFilterNavPoints(GridPoints, QueryInstance); StoreNavPoints(GridPoints, QueryInstance); }
// execution EBTNodeResult::Type UAIE_GoToRandom_BTTaskNode::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { /* call super * should aquire refrences for our BehaviorTreeComp, BlackboardComp, AIController, and BotCharacter * will return EBTNodeResult::Succeeded if we have all of them * will return EBTNodeResult::Failed if it failed to grab any of them */ EBTNodeResult::Type resultFromSuperExecution = Super::ExecuteTask(OwnerComp, NodeMemory); // check that we successfully grabbed the BehaviorTreeComp, BlackboardComp, AIController, and BotCharacter if (resultFromSuperExecution == EBTNodeResult::Succeeded) { // check that we can get the World if (GetWorld()) { // get the current nav system from the world UNavigationSystem* navSystem = UNavigationSystem::GetCurrent(GetWorld()); // check that we have a nav system if (navSystem) { // get our actors current location to pe used as our start position FVector startPosi = BotCharacter->GetActorLocation(); // create a nav location to be used as our end position // default will be set to our current position in case of failure to find a suitable end position FNavLocation endPosi = FNavLocation(startPosi); // attempt to get a random new position if (navSystem->GetRandomReachablePointInRadius(startPosi, searchRadius, endPosi)) { // if we were successfull in finding a new location get the MoveToLocation BlackboardKeyID FBlackboard::FKey BlackboardKey_MoveToLocation = Blackboard->GetKeyID("MoveToLocation"); // check that we got the key if ( Blackboard->IsValidKey( BlackboardKey_MoveToLocation)) { // set the MoveToLocation BlackboardKeyID to our new location Blackboard->SetValue<UBlackboardKeyType_Vector>(BlackboardKey_MoveToLocation, endPosi.Location); // return succeeded now that we have set up our new loacation return EBTNodeResult::Succeeded; } else { // return Aborted if we can't find the Key as it will never succeed without a proper Key if (bForceSuccess) { return EBTNodeResult::Succeeded; } return EBTNodeResult::Aborted; } } // return in progress if their are currently no valid locations if (bForceSuccess) { return EBTNodeResult::Succeeded; } return EBTNodeResult::InProgress; } } } // we will only get here if execution fails so we will check if force success is on if (bForceSuccess) { // if force success is on we will return Succeeded anyway return EBTNodeResult::Succeeded; } // we want to return Failed after the force success check return EBTNodeResult::Failed; }
FNavLocation UNavigationComponent::GetRandomPointOnNavMesh() const { #if WITH_RECAST ARecastNavMesh* const Nav = (ARecastNavMesh*)GetWorld()->GetNavigationSystem()->GetMainNavData(NavigationSystem::Create); if (Nav) { return Nav->GetRandomPoint(); } #endif // WITH_RECAST return FNavLocation(); }
FNavLocation UNavigationComponent::ProjectPointToNavigation(const FVector& Location) const { FNavLocation OutLocation(Location); if (GetNavData() != NULL) { if (!MyNavData->ProjectPoint(Location, OutLocation, MyNavData->GetDefaultQueryExtent())) { OutLocation = FNavLocation(); } } return OutLocation; }
void UEnvQueryGenerator_OnCircle::GenerateItemsForCircle(uint8* ContextRawData, UEnvQueryItemType* ContextItemType, const FVector& CenterLocation, const FVector& StartDirection, int32 StepsCount, float AngleStep, FEnvQueryInstance& OutQueryInstance) const { TArray<FNavLocation> ItemCandidates; ItemCandidates.AddZeroed(StepsCount); for (int32 Step = 0; Step < StepsCount; ++Step) { ItemCandidates[Step] = FNavLocation(CenterLocation + StartDirection.RotateAngleAxis(AngleStep*Step, FVector::UpVector)); } switch (TraceData.TraceMode) { case EEnvQueryTrace::Navigation: { ANavigationData* NavData = const_cast<ANavigationData*>(FEQSHelpers::FindNavigationDataForQuery(OutQueryInstance)); if (NavData) { FEQSHelpers::RunNavRaycasts(*NavData, TraceData, CenterLocation, ItemCandidates); } } break; case EEnvQueryTrace::Geometry: FEQSHelpers::RunPhysRaycasts(OutQueryInstance.World, TraceData, CenterLocation, ItemCandidates); break; case EEnvQueryTrace::None: // Just accept the ItemCandidates as they already are (points on a circle), without using navigation OR collision. break; default: UE_VLOG(Cast<AActor>(OutQueryInstance.Owner.Get()), LogEQS, Warning, TEXT("UEnvQueryGenerator_OnCircle::CalcDirection has invalid value for TraceData.TraceMode. Query: %s"), *OutQueryInstance.QueryName); break; } ProjectAndFilterNavPoints(ItemCandidates, OutQueryInstance); AddItemDataForCircle(ContextRawData, ContextItemType, ItemCandidates, OutQueryInstance); }
void UEnvQueryTest_Project::RunTest(FEnvQueryInstance& QueryInstance) const { BoolValue.BindData(QueryInstance.Owner.Get(), QueryInstance.QueryID); bool bWantsProjected = BoolValue.GetValue(); UEnvQueryItemType_Point* ItemTypeCDO = QueryInstance.ItemType->GetDefaultObject<UEnvQueryItemType_Point>(); if (ItemTypeCDO == nullptr) { return; } if (ProjectionData.TraceMode == EEnvQueryTrace::Navigation) { const ANavigationData* NavData = FEQSHelpers::FindNavigationDataForQuery(QueryInstance); if (NavData) { TSharedPtr<const FNavigationQueryFilter> NavigationFilter = UNavigationQueryFilter::GetQueryFilter(*NavData, ProjectionData.NavigationFilter); TArray<FNavigationProjectionWork> Workload; Workload.Reserve(QueryInstance.Items.Num()); const FVector VerticalOffset = (ProjectionData.ProjectDown == ProjectionData.ProjectUp) ? FVector::ZeroVector : FVector(0, 0, (ProjectionData.ProjectUp - ProjectionData.ProjectDown) / 2); for (int32 Idx = 0; Idx < QueryInstance.Items.Num(); Idx++) { if (QueryInstance.Items[Idx].IsValid()) { const FVector& ItemLocation = GetItemLocation(QueryInstance, Idx); Workload.Add(FNavigationProjectionWork(ItemLocation + VerticalOffset)); } } const FVector ProjectionExtent(ProjectionData.ExtentX, ProjectionData.ExtentX, (ProjectionData.ProjectDown + ProjectionData.ProjectUp) / 2); NavData->BatchProjectPoints(Workload, ProjectionExtent, NavigationFilter); int32 Idx = 0; for (FEnvQueryInstance::ItemIterator It(this, QueryInstance); It; ++It, Idx++) { const bool bProjected = Workload[Idx].bResult; if (bProjected) { ItemTypeCDO->SetItemNavLocation(It.GetItemData(), Workload[Idx].OutLocation); } It.SetScore(TestPurpose, FilterType, bProjected, bWantsProjected); } } } else if (ProjectionData.TraceMode == EEnvQueryTrace::Geometry) { TArray<FNavLocation> Workload; TArray<uint8> TraceHits; Workload.Reserve(QueryInstance.Items.Num()); for (int32 Idx = 0; Idx < QueryInstance.Items.Num(); Idx++) { if (QueryInstance.Items[Idx].IsValid()) { const FVector& ItemLocation = GetItemLocation(QueryInstance, Idx); Workload.Add(FNavLocation(ItemLocation)); } } FEQSHelpers::RunPhysProjection(QueryInstance.World, ProjectionData, Workload, TraceHits); int32 Idx = 0; for (FEnvQueryInstance::ItemIterator It(this, QueryInstance); It; ++It, Idx++) { const bool bProjected = TraceHits.IsValidIndex(Idx) && TraceHits[Idx]; if (bProjected) { ItemTypeCDO->SetItemNavLocation(It.GetItemData(), Workload[Idx]); } It.SetScore(TestPurpose, FilterType, bProjected, bWantsProjected); } } }
void UEnvQueryGenerator_Donut::GenerateItems(FEnvQueryInstance& QueryInstance) const { TArray<FVector> CenterPoints; QueryInstance.PrepareContext(Center, CenterPoints); if (CenterPoints.Num() <= 0) { return; } UObject* BindOwner = QueryInstance.Owner.Get(); InnerRadius.BindData(BindOwner, QueryInstance.QueryID); OuterRadius.BindData(BindOwner, QueryInstance.QueryID); NumberOfRings.BindData(BindOwner, QueryInstance.QueryID); PointsPerRing.BindData(BindOwner, QueryInstance.QueryID); ArcAngle.BindData(BindOwner, QueryInstance.QueryID); float ArcAngleValue = ArcAngle.GetValue(); float InnerRadiusValue = InnerRadius.GetValue(); float OuterRadiusValue = OuterRadius.GetValue(); int32 NumRings = NumberOfRings.GetValue(); int32 NumPoints = PointsPerRing.GetValue(); if ((InnerRadiusValue <= 0.f) || (OuterRadiusValue <= 0.f) || (InnerRadiusValue > OuterRadiusValue) || (NumRings < 1) || (NumPoints < 1)) { return; } const float ArcBisectDeg = GetArcBisectorAngle(QueryInstance); const float ArcAngleDeg = FMath::Clamp(ArcAngleValue, 0.0f, 360.0f); const float RadiusDelta = (OuterRadiusValue - InnerRadiusValue) / (NumRings - 1); const float AngleDelta = 2.0 * PI / NumPoints; float SectionAngle = FMath::DegreesToRadians(ArcBisectDeg); TArray<FNavLocation> Points; Points.Reserve(NumPoints * NumRings); for (int32 SectionIdx = 0; SectionIdx < NumPoints; SectionIdx++, SectionAngle += AngleDelta) { if (IsAngleAllowed(SectionAngle, ArcBisectDeg, ArcAngleDeg, bDefineArc)) { const float SinValue = FMath::Sin(SectionAngle); const float CosValue = FMath::Cos(SectionAngle); float RingRadius = InnerRadiusValue; for (int32 RingIdx = 0; RingIdx < NumRings; RingIdx++, RingRadius += RadiusDelta) { const FVector RingPos(RingRadius * CosValue, RingRadius * SinValue, 0.0f); for (int32 ContextIdx = 0; ContextIdx < CenterPoints.Num(); ContextIdx++) { const FNavLocation PointPos = FNavLocation(CenterPoints[ContextIdx] + RingPos); Points.Add(PointPos); } } } } ProjectAndFilterNavPoints(Points, QueryInstance); StoreNavPoints(Points, QueryInstance); }