Fix EQS firing position: invalid BB vector check, AlreadyAtGoal fallback
- LastKnownTargetPosition check now filters FLT_MAX/InvalidLocation (not just zero) - EQS result with AlreadyAtGoal triggers fallback advance instead of no-op - bProjectGoal enabled for EQS move to handle NavMesh projection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
59a23e61db
commit
25abd59512
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -227,8 +227,12 @@ void UPS_AI_Behavior_BTTask_Attack::TickTask(
|
|||||||
{
|
{
|
||||||
// No LOS and idle → find a firing position
|
// No LOS and idle → find a firing position
|
||||||
// Check if investigation (last known position) is active
|
// Check if investigation (last known position) is active
|
||||||
|
// ClearValue sets vectors to FAISystem::InvalidLocation, not zero — must check both
|
||||||
const FVector LastKnownPos = BB->GetValueAsVector(PS_AI_Behavior_BB::LastKnownTargetPosition);
|
const FVector LastKnownPos = BB->GetValueAsVector(PS_AI_Behavior_BB::LastKnownTargetPosition);
|
||||||
if (!LastKnownPos.IsZero())
|
const bool bHasLastKnown = !LastKnownPos.IsZero() &&
|
||||||
|
!LastKnownPos.ContainsNaN() &&
|
||||||
|
LastKnownPos.X < 1e30f; // Filter out FLT_MAX / InvalidLocation
|
||||||
|
if (bHasLastKnown)
|
||||||
{
|
{
|
||||||
// Investigation mode: go to last known position
|
// Investigation mode: go to last known position
|
||||||
AIC->MoveToLocation(
|
AIC->MoveToLocation(
|
||||||
@ -336,6 +340,7 @@ void UPS_AI_Behavior_BTTask_Attack::TickTask(
|
|||||||
*AIC->GetName());
|
*AIC->GetName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EBTNodeResult::Type UPS_AI_Behavior_BTTask_Attack::AbortTask(
|
EBTNodeResult::Type UPS_AI_Behavior_BTTask_Attack::AbortTask(
|
||||||
@ -427,20 +432,9 @@ void UPS_AI_Behavior_BTTask_Attack::OnFiringPositionQueryFinished(
|
|||||||
|
|
||||||
AActor* Target = WeakTarget.Get();
|
AActor* Target = WeakTarget.Get();
|
||||||
|
|
||||||
if (Result.IsValid() && Result->IsSuccessful())
|
// Fallback lambda: advance directly toward target
|
||||||
|
auto FallbackAdvance = [&](const TCHAR* Reason)
|
||||||
{
|
{
|
||||||
const FVector FiringPos = Result->GetItemAsLocation(0);
|
|
||||||
AIC->MoveToLocation(
|
|
||||||
FiringPos, 50.0f, /*bStopOnOverlap=*/true,
|
|
||||||
/*bUsePathfinding=*/true, /*bProjectGoal=*/false, /*bCanStrafe=*/false);
|
|
||||||
Memory->bSeekingFiringPos = true;
|
|
||||||
|
|
||||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS found firing position %s"),
|
|
||||||
*AIC->GetName(), *FiringPos.ToString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// EQS found nothing — fallback: advance toward target
|
|
||||||
if (Target)
|
if (Target)
|
||||||
{
|
{
|
||||||
const float MidRange = (Memory->MinRange + Memory->MaxRange) * 0.5f;
|
const float MidRange = (Memory->MinRange + Memory->MaxRange) * 0.5f;
|
||||||
@ -449,9 +443,32 @@ void UPS_AI_Behavior_BTTask_Attack::OnFiringPositionQueryFinished(
|
|||||||
/*bUsePathfinding=*/true, /*bProjectGoal=*/true, /*bCanStrafe=*/false);
|
/*bUsePathfinding=*/true, /*bProjectGoal=*/true, /*bCanStrafe=*/false);
|
||||||
Memory->bSeekingFiringPos = true;
|
Memory->bSeekingFiringPos = true;
|
||||||
}
|
}
|
||||||
|
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: %s, fallback advance toward target"),
|
||||||
|
*AIC->GetName(), Reason);
|
||||||
|
};
|
||||||
|
|
||||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS no result, fallback advance"),
|
if (Result.IsValid() && Result->IsSuccessful())
|
||||||
*AIC->GetName());
|
{
|
||||||
|
const FVector FiringPos = Result->GetItemAsLocation(0);
|
||||||
|
const EPathFollowingRequestResult::Type MoveResult = AIC->MoveToLocation(
|
||||||
|
FiringPos, 50.0f, /*bStopOnOverlap=*/true,
|
||||||
|
/*bUsePathfinding=*/true, /*bProjectGoal=*/true, /*bCanStrafe=*/false);
|
||||||
|
|
||||||
|
if (MoveResult == EPathFollowingRequestResult::RequestSuccessful)
|
||||||
|
{
|
||||||
|
Memory->bSeekingFiringPos = true;
|
||||||
|
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Attack: EQS moving to firing position %s"),
|
||||||
|
*AIC->GetName(), *FiringPos.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// AlreadyAtGoal or Failed — EQS position is too close or unreachable
|
||||||
|
FallbackAdvance(TEXT("EQS position unreachable or too close"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FallbackAdvance(TEXT("EQS no result"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,6 +48,7 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, Category = "Attack|LOS", meta = (ClampMin = "0.1", ClampMax = "1.0"))
|
UPROPERTY(EditAnywhere, Category = "Attack|LOS", meta = (ClampMin = "0.1", ClampMax = "1.0"))
|
||||||
float LOSCheckInterval = 0.2f;
|
float LOSCheckInterval = 0.2f;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EQS query asset for finding a firing position with clear LOS.
|
* EQS query asset for finding a firing position with clear LOS.
|
||||||
* Compose in editor: OnCircle generator + LineOfSight filter + Distance tests.
|
* Compose in editor: OnCircle generator + LineOfSight filter + Distance tests.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user