AIPerceptionSystem SenseID counter not reset after compile hot reload

I’m using an AIPerceptionComponent in my AIController class that configures a sense.

Then on UAIPerceptionComponent::OnRegister(…) the component will call UAIPerceptionSystem::RegisterSenseClass(…).

Now if that sense is not registered yet it will call

	UAISense* SenseCDO = GetMutableDefault<UAISense>(SenseClass);
	SenseID = SenseCDO->UpdateSenseID();

It will eventually end up here:

   FAINamedID(const FName& InName)
	: Index(GetCounter().GetNextAvailableID()), Name(InName)
    {}

According to the retrieved index it will add elements to the Senses array:

	const int32 ItemsToAdd = SenseID.Index - Senses.Num() + 1;
	Senses.AddZeroed(ItemsToAdd);

This works find except in the following case:

  • Running the editor in debug mode start a pie session.
  • compile the code again leading to a hot reload in the editor (make a small insignificant change if it won’t compile otherwise)
  • play a pie session

This will go through the above mentioned steps of creating a sense.
But this time the SenseID.Index will be 1 (instead of 0) which leads to 2 items added to the Senses array.
Only the second entry is updated.

This leads to a crash in:

void UAIPerceptionSystem::StartPlay()
{
	for (UAISense* Sense : Senses)
	{
		if (Sense->ShouldAutoRegisterAllPawnsAsSources())  // CRASH

It tries to access Senses[0] which will be null. Senses[1] contains the actually created sense.

I’m running Mac OSX version 10.10.5.

My guess is that it has something to do with the counter

static TCounter& GetCounter() 
{ 
	static TCounter Counter;
	return Counter;
}

and

Type GetNextAvailableID() { return NextAvailableID++; }

Seems like the static counter is not reset when compiling for a hot reload… Odd.

Please let me know if you need more info.

Hey -

Does this crash occur in a new project with no additional content? Can you post the steps you took that caused the crash and the code used to setup your AI Perception? Can you also post the callstack and log files from the crash for additional information?

Cheers

Hey ,

thanks for the answer. I was able to reproduce it in a blank c++ project. Here my classes:

Simply follow these steps:

  1. Create a new Pawn BlueprintClass, us the MyAIController and place it into the world.
  2. Start a PIE session
  3. Quit PIE session
  4. Make a minor change in “My” code and recompile (it suffices to delete one letter, add it again, save and compile)
  5. Editor should have done a hot reload after compile finished
  6. Now play another PIE session

That should lead to the crash.
Call stack:

I noticed when registering an existing sense class (sight, hearing, etc…) then UAIPerceptionSystem::RegisterSenseClass will enter different scopes of the function:

	FAISenseID SenseID = UAISense::GetSenseID(SenseClass);
	if (SenseID.IsValid() == false) 			// this is only entered when using a custom sense
	{
		UAISense* SenseCDO = GetMutableDefault<UAISense>;

Am I missing something in my custom sense class? However it would be odd if it works the first time, and after recompiling it crashes.

Well, hope this helps. If you have any more questions please let me know.

Hey -

Thank you for the reproduction steps. I was able to reproduce the crash you described and have entered a bug (UE-21586) for further investigation.

Cheers

It does not crash any more as of 4.9.2 Hotfix. But merely because a check has been added for checking if the Sense in the Senses array is null or not.
However, the Senses array still grows by one null element each time the editor does a hot reload after compiling the code.