Order of Operations for AIController derived classes

When you make an Unreal Engine character (based on the ACharacter class) and it has a controller derived from the AAIController class, calls to the methods BeginPlay() and OnPossess() happen in a different sequence depending on how the character is created:

  • if the character is placed in the level using the editor, OnPossess() is called before BeginPlay()
  • if the character is spawned using (say) World->SpawnActor() then BeginPlay() is called before OnPossess()

This means if you initialize the AI blackboard in the OnPossess() call and write values into the blackboard on the BeginPlay() call, this will work when the character is placed in the level but will silently fail when the character is spawned at runtime.

It will fail because the keys have not been created in blackboard yet, and it will be silent because a call like this:

BlackboardComponent->SetValueAsObject( ... )

does not have a return value which can be tested for failure.

Other Effects

This has other effects when considering the player pawn. If you retrieve the player pawn using a line like this:

APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);

in your implementation of BeginPlay(), in the case where the character is placed in the level PlayerPawn will be null, but if the character is spawned at runtime it will have the expected value.

So you can't handle the different call sequences by just putting all the code into OnPossess(), because the values it sees also depend on how the character was created.

Reference

Advanced Debugging In Unreal Engine

Feedback

Please leave any feedback about this article here