If I understand you correctly, you don’t want actors that are hidden behind something to be perceived. If that’s the case, here’s what I’ve found:
Firstly, the AIPerception sight sense does perform a line trace to determine if a target is occluded or not, but it only considers static objects - see here. You need to register your Epic user name on Github to access this page, so I’ll also add the relevant line below:
const bool bHit = World->LineTraceSingleByObjectType(HitResult, Listener.CachedLocation, TargetLocation
, FCollisionQueryParams(NAME_AILineOfSight, true, Listener.Listener->GetBodyActor()));
I couldn’t find any documentation for it, but after looking through the code I found that you could override this using the
AISightTargetInterface interface, but this will require C++.
Here’s how to use it:
First you need your pawn to implement
IMPORTANT: Your target pawn must implement this, ie. the pawn that is being detected, not the one doing the detecting.
Copy the relevant parts into your pawn class.
// Add this >>
class AMyCustomTargetPawn : public APawn, public IAISightTargetInterface // << Extend the 'IAISightTargetInterface' interface
// Add the 'CanBeSeenFrom' definition >>
/** Implementation should check whether from given ObserverLocation
* implementer can be seen. If so OutSeenLocation should contain
* first visible location
* Return sight strength for how well the target is seen.
virtual bool CanBeSeenFrom(const FVector& ObserverLocation, FVector& OutSeenLocation, int32& NumberOfLoSChecksPerformed, float& OutSightStrength, const AActor* IgnoreActor = NULL) const;
Then for the implementation in your .cpp file; this was copied straight from AISense_Sight.cpp (See the link I provided at the top), except I changed it to also check for dynamic objects:
bool AMyCustomTargetPawn::CanBeSeenFrom(const FVector& ObserverLocation, FVector& OutSeenLocation, int32& NumberOfLoSChecksPerformed, float& OutSightStrength, const AActor* IgnoreActor) const
static const FName NAME_AILineOfSight = FName(TEXT("TestPawnLineOfSight"));
const bool bHit = GetWorld()->LineTraceSingleByObjectType(HitResult, ObserverLocation, GetActorLocation()
, FCollisionObjectQueryParams(ECC_TO_BITFIELD(ECC_WorldStatic) | ECC_TO_BITFIELD(ECC_WorldDynamic)) // << Changed this line
, FCollisionQueryParams(NAME_AILineOfSight, true, IgnoreActor));
// Add any other checks you want to perform here
if (bHit == false || (HitResult.Actor.IsValid() && HitResult.Actor->IsOwnedBy(this)))
OutSeenLocation = GetActorLocation();
OutSightStrength = 1;
OutSightStrength = 0;
Change, or add in any other extra logic you want; and if you’re using blueprints, make sure that you change it so that your pawn blueprint’s parent is set to this new class instead of
At this point it should work - dynamic objects should also block the perception component’s line of site.