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:
FHitResult HitResult;
const bool bHit = World->LineTraceSingleByObjectType(HitResult, Listener.CachedLocation, TargetLocation
, FCollisionObjectQueryParams(ECC_WorldStatic)
, 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:
Step 1
First you need your pawn to implement AISightTargetInterface
.
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 >>
#include "Perception/AISightTargetInterface.h"
class AMyCustomTargetPawn : public APawn, public IAISightTargetInterface // << Extend the 'IAISightTargetInterface' interface
{
public:
// Add the 'CanBeSeenFrom' definition >>
// IAISightTargetInterface:
/** 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;
};
Step 2
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"));
FHitResult HitResult;
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));
NumberOfLoSChecksPerformed++;
// Add any other checks you want to perform here
// ...
if (bHit == false || (HitResult.Actor.IsValid() && HitResult.Actor->IsOwnedBy(this)))
{
OutSeenLocation = GetActorLocation();
OutSightStrength = 1;
return true;
}
OutSightStrength = 0;
return false;
}
Step 3
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 Pawn
.
At this point it should work - dynamic objects should also block the perception component’s line of site.