Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

FAIStimulus::IsExpired() not working?

I'm trying to retrieve an actor that has been sensed by an AIPerceptionComponen that has not expired yet. The AIPerceptionComponent is part of the AIController and the max age of the AI Sight Config has been set to 2 seconds for testing. The following code is run every 0.5 seconds:

 TArray<AActor*> Actors;
 AISensingComponent->GetPerceivedActors(UAISenseConfig_Sight::StaticClass(), Actors);
 if (Actors.Num() < 1)
 const FActorPerceptionInfo* ActorInfo = AISensingComponent->GetActorInfo(*Actors[0]);
 if (ActorInfo->LastSensedStimuli[0].IsExpired())
 GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, "I still know where you are!");
 GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, FString::FromInt(ActorInfo->LastSensedStimuli[0].GetAge()));

However, the two messages are always shown on the screen once an Actor has been seen. The age also seems to go from 0 to 1, to -2147483648 where the last number seems to me some sort of indication that the stimuli has expired. This gives me the idea that IsExpired() might possibly be not working, any ideas?

Product Version: UE 4.11
more ▼

asked Apr 23 '16 at 01:35 PM in C++ Programming

avatar image

135 9 62 20

avatar image v.s. Apr 24 '16 at 05:42 PM

Have you tried to use a gameplay debugger, and what is its visual output?

 /** this means the stimulus was originally created with a "time limit" and this time has passed. 
      *    Expiration also results in calling MarkNoLongerSensed */
     uint32 bExpired:1;    

What a result of the MarkNoLongerSensed()? Result = WasSuccessfullySensed()

avatar image Truun Apr 24 '16 at 06:20 PM

Good idea, the gameplay debugger shows this: alt text

alt text

alt text

How would I get the output of marknolongersensed, add a breakpoint there?

seen.png (957.0 kB)
losingisght.png (949.1 kB)
sightlost.png (901.4 kB)
avatar image v.s. Apr 24 '16 at 06:39 PM

Try to debug at Stimulus.MarkExpired

  bool UAIPerceptionComponent::AgeStimuli(const float ConstPerceptionAgingRate)
         bool bExpiredStimuli = false;
         for (TActorPerceptionContainer::TIterator It(PerceptualData); It; ++It)
             FActorPerceptionInfo& ActorPerceptionInfo = It->Value;
             for (FAIStimulus& Stimulus : ActorPerceptionInfo.LastSensedStimuli)
                 // Age the stimulus. If it is active but has just expired, mark it as such
                 if (Stimulus.AgeStimulus(ConstPerceptionAgingRate) == false 
                     && (Stimulus.IsActive() || Stimulus.WantsToNotifyOnlyOnPerceptionChange())
                     && Stimulus.IsExpired() == false)
                     AActor* TargetActor = ActorPerceptionInfo.Target.Get();
                     if (TargetActor)
                         Stimulus.MarkExpired(); // try to debug there
                         RegisterStimulus(TargetActor, Stimulus);
                         bExpiredStimuli = true;
         return bExpiredStimuli;

avatar image Truun Apr 24 '16 at 07:32 PM

Stimulus.MarkExpired() gets called when that green sphere disappears.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

I noticed that the MarkExpired call takes place only when the target is out of lose range (pink).

 float GetAge() const { return Strength > 0 ? Age : NeverHappenedAge; }

In my case at expired point: Age = 2.09 ExpirationAge = 2.0 Strength = 1.0 bExpired = 1

more ▼

answered Apr 24 '16 at 08:49 PM

avatar image

347 9 12 26

avatar image Truun Apr 24 '16 at 09:44 PM

I also get it round that point, but for some reason IsExpired() still returns false and therefore those messages still get printed.

avatar image v.s. Apr 24 '16 at 10:40 PM

Target is invalid after it was expired and bExpired = 0. Use FAIStimulus::IsActive() for validation of the LastSensedStimuli.

avatar image Truun Apr 24 '16 at 11:08 PM

But IsActive() is already set to false when the AI loses sight not when the age is greater than it's experiation age.

avatar image v.s. Apr 25 '16 at 05:23 AM

Hmm, okey. Try to use

bool IsExpired = AgeStimulus(0.f) == false;

 /** @return false when this stimulus is no longer valid, when it is Expired */
     FORCEINLINE bool AgeStimulus(float ConstPerceptionAgingRate) 
         Age += ConstPerceptionAgingRate; 
         return Age < ExpirationAge;
avatar image Truun Apr 25 '16 at 11:57 AM

well the problem with that is:

const FActorPerceptionInfo* ActorInfo = AISensingComponent->GetActorInfo(*Actors[0]);

so ActorInfo->LastSensedStimuli[0] is constant and therefore you can't apply AgeStimulus on it.

avatar image v.s. Apr 25 '16 at 12:20 PM

Copy FAIStimulus to a local variable by value.

avatar image Truun Apr 25 '16 at 12:43 PM

Well that works, but is that really the way to go?

avatar image v.s. Apr 25 '16 at 12:53 PM

Due to the lack of methods for accessing to ExpirationAge this should work. Elapsed time is added each time in AgeStimuli. It works.

avatar image v.s. Apr 25 '16 at 01:15 PM

When time will expire then Age == FLT_MAX and ExpiredAge == FLT_MAX too.

avatar image Truun Apr 25 '16 at 01:20 PM

I think I'll use that then, that seems like the cleanest, thanks! Still does IsExpired() then work as intended or not?

avatar image v.s. Apr 25 '16 at 01:47 PM
 void UAIPerceptionComponent::HandleExpiredStimulus(FAIStimulus& StimulusStore)
     ensure(StimulusStore.IsExpired() == true);
     StimulusStore = FAIStimulus();


 // default constructor
         : ... bExpired(false)

At HandleExpiredStimulus bExpired was reseted to 0. Maybe it's a bug. But the more it seems that this behavior is not provided. LastSensedStimuli[0] zero should be replaced with the ID of the sense FAIStimulus::Type. LastSensedStimuli can be rewritten, I think you can not rely on the data that is written in it, or they will have to check every tick.

 if (PerceptualInfo->LastSensedStimuli.Num() <= SourcedStimulus->Stimulus.Type)
             const int32 NumberToAdd = SourcedStimulus->Stimulus.Type - PerceptualInfo->LastSensedStimuli.Num() + 1;
             for (int32 Index = 0; Index < NumberToAdd; ++Index)
         FAIStimulus& StimulusStore = PerceptualInfo->LastSensedStimuli[SourcedStimulus->Stimulus.Type];
avatar image Truun Apr 26 '16 at 05:46 PM

I guess I'll go with this then, thanks! if (ActorInfo->LastSensedStimuli[SightConfig->GetSenseID()].GetAge() == FLT_MAX)

avatar image cgrebeld May 24 '16 at 09:26 PM

I'm seeing this in 4.11 as well. I'm kind of lost on what the right answer was here though. My workaround so far is to check perception on my target every once in awhile because I'm not getting notified about expired Sight stimuli.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question