The code in UWorld::RemoveFromWorld that removes Pawns that are about to be streamed out does not check to see if the pointer that it sets is null prior to using it. In cases where Pawns are rapidly moving in and out of sublevels, this can cause a crash in the subsequent functions.
Licensee reporting this provided a reproduction case for this, but the setup would require a complicated project with multiple intricate sublevels (resulting in the loading times for said sublevel being higher than with a blank one), so the crash has not been reproduced locally.
Current code:
// Remove any pawns from the pawn list that are about to be streamed out for( FConstPawnIterator Iterator = GetPawnIterator(); Iterator; ++Iterator ) { APawn* Pawn = Iterator->Get(); if (Pawn->IsInLevel(Level)) { RemovePawn(Pawn); --Iterator; } else if (UCharacterMovementComponent* CharacterMovement = Cast<UCharacterMovementComponent>(Pawn->GetMovementComponent())) { // otherwise force floor check in case the floor was streamed out from under it CharacterMovement->bForceNextFloorCheck = true; } }
Suggested code:
// Remove any pawns from the pawn list that are about to be streamed out for( FConstPawnIterator Iterator = GetPawnIterator(); Iterator; ++Iterator ) { APawn* Pawn = Iterator->Get(); if (Pawn != nullptr) { if (Pawn->IsInLevel(Level)) { RemovePawn(Pawn); --Iterator; } else if (UCharacterMovementComponent* CharacterMovement = Cast<UCharacterMovementComponent>(Pawn->GetMovementComponent())) { // otherwise force floor check in case the floor was streamed out from under it CharacterMovement->bForceNextFloorCheck = true; } } }
Regression?: No
This code was present in 4.15
N/A - Source code issue
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-53339 in the post.