AI Perception SuccessfullySensed issues

I’m currently using the AI Perception system for my AI to detect characters and relevant actors in the world (grenades, for example). This works perfectly fine for all characters, however when it comes to detecting other actors they will initially successfully sense the actor in the first perception update and then any frame after that fail to successfully sense them.

Here is a webm to show off the perception debugger and logs I’m getting:
http://puu.sh/raOAv/6ab6250e3c.webm

In the webm sample I’ve posted here, the player character that it successfully detects derives from the character class, and therefore has the default pawn class sensory stimuli.

The grenades I throw (basic sphere meshes) are actors set up in c++ with a UAIPerceptionStimuliSourceComponent for perception. I have also tested these with a BP AI Perception Stimuli Source for sight and I get the same issue of detecting them initially and then just failing the sense, as indicated in the logs.

The ragdoll bodies I spawn in are a BP class derived from APawn, with the same stimuli as the character classes have, with a single static mesh. These also suffer from the same problem as the grenades.

Outside of the webm I have tested it in just about every number of combinations of parent classes and components I can think of, with both BP and C++ classes. They’ve all had the same problem. Am I doing something wrong here? Why is it detecting the player and other AI properly but never other actors?

Here’s the code used for the AI controller’s perception updates:

// used to check perceived updates. Called by delegate.
void ABaseAIController::OnSense(TArray<AActor*> TestActors)
{
	for (int32 i = 0; i < TestActors.Num(); i++)
	{
		AActor* TestActor = Cast<AActor>(TestActors[i]);
		if (TestActor)
		{
			const FActorPerceptionInfo* ActorInfo = AIPerceptionComp->GetActorInfo(*TestActor);
			if (ActorInfo && ActorInfo->LastSensedStimuli.Num() > 0)
			{
				for (int32 j = 0; j < ActorInfo->LastSensedStimuli.Num(); j++)
				{
					if (ActorInfo->LastSensedStimuli[j].WasSuccessfullySensed())
					{
						//////// SIGHT ////////
						if (ActorInfo->LastSensedStimuli[j].Type == SightConfig->GetSenseID())
						{
							UE_LOG(LogGeneral, Log, TEXT("sensed pawn %s"), *TestActor->GetName());
						}
					}
					else
					{
						UE_LOG(LogGeneral, Log, TEXT("lost pawn sense"));
					}
				}
			}
		}
	}
}

Hey Xavice,

For the ragdoll’s what happens is your AI tries to look at the capsule components position but the ragdoll is on the floor, so the linetrace never ‘sees’ anything, to fix this you can implement an “IAISightTargetInterface” on your AI-character and override the CanBeSeenFrom() function to make sure he actually looks at the mesh’s position. This way Unreal will not use the default trace which is only a linetrace to the actors location.

Don’t forget to include: “Perception/AISightTargetInterface.h”.
Let me know if this fixed your problems :slight_smile:

Hope this helps,
Elias

Thank you for the response. That’s what I was looking at myself actually. Unfortunately that did not fix the issue. There must be another reason behind it in the AI Sense code. I’ll look through it more carefully when I get time. I tested this with my grenade actor and despite a successful trace, it loses sight. Even if I make the CanBeSeenFrom call return true only, it does not keep sight of the actor. Log and debugger displaying the exact same behaviour.

Image showing trace

Overridden code here:

	virtual bool CanBeSeenFrom(const FVector& ObserverLocation, FVector& OutSeenLocation, int32& NumberOfLoSChecksPerformed, float& OutSightStrength, const AActor* IgnoreActor = NULL) const override
	{
		OutSeenLocation = GrenadeMesh->GetComponentLocation();	// static mesh for grenade
		NumberOfLoSChecksPerformed = 0;
		OutSightStrength = 0.0f;
		bool success = false;

		FVector StartTrace = ObserverLocation;
		FVector EndTrace = OutSeenLocation;
		FHitResult HitData(ForceInit);

		if (GetWorld()->LineTraceSingleByChannel(HitData, StartTrace, EndTrace, ECC_Visibility))
		{
			NumberOfLoSChecksPerformed++;
			OutSightStrength += 1.0f;
			success = true;
		}

		if (success)
		{
			DrawDebugLine(GetWorld(), ObserverLocation, OutSeenLocation, FColor::Red, false, 0.0f, 000, 2.5f);
		}
		else
		{
			DrawDebugLine(GetWorld(), ObserverLocation, OutSeenLocation, FColor::Blue, false, 0.0f, 000, 2.5f);
		}
		
		return success;
	}

Oh, I also remember some strange behavior when i was working on my perception but can’t remember how I fixed it again… Could you try and move your if (ActorInfo->LastSensedStimuli[j].WasSuccessfullySensed()) check after your sight check? maybe there is some weird sensing stuff going on.

Thank you. Doing that seems to be working.