Possibly a bug or ConstructorHelpers misuse?

I have such code in MyGameMode.cpp constructor

	bool bSingletonIsValid;
	UTreadwaterGameSingleton *Singleton = UTreadwaterBlueprintLibrary::GetSingleton(bSingletonIsValid);
	if (bSingletonIsValid) {
		switch (Singleton->SelectedCharacter) {
		case ECharacterType::CT_Wraith:
			{
				// set default pawn class to our Blueprinted character
				static ConstructorHelpers::FClassFinder<APawn> WraithPlayerPawnBPClass(TEXT("/Game/Treadwater/Character/Blueprints/WraithPlayerThirdPersonCharacter"));
				if (WraithPlayerPawnBPClass.Class != NULL) {
					DefaultPawnClass = WraithPlayerPawnBPClass.Class;
				}
			}
			break;
		case ECharacterType::CT_Dom:
			{
				// set default pawn class to our Blueprinted character
				static ConstructorHelpers::FClassFinder<APawn> DomPlayerPawnBPClass(TEXT("/Game/Treadwater/Character/Blueprints/DomPlayerThirdPersonCharacter"));
				if (DomPlayerPawnBPClass.Class != NULL) {
					DefaultPawnClass = DomPlayerPawnBPClass.Class;
				}
			}
			break;
		case ECharacterType::CT_None:
			{
				DefaultPawnClass = nullptr;
			}
			break;
		}

		Singleton->SetGameMode(this);
	}

It has two static ConstructorHelpers variables, which got reset to null in packaged build.
I run my game, load level, init character based on var in singleton. It works ok. But after finishing the level and reloading it all the same code sets None to DefaultPawnClass.

This bug only appears in packaged build. everything works ok in Unreal Editor.

I have this levels
StartGame.umap
→ CharacterSelect.umap as sublevel

LevelLoader.umap
→ BigGameMap.umap as sublevel

sublevel are loaded using level streaming. Bug occurs after I do OpenLevel(LevelLoader) in my blueprint after playing on BigGameMap.

trying use not static ConstructorHelpers, hope it fixes the error.

Crash occurs in AGameMode::ChoosePlayerStart_Implementation

Upd:
Removing static fixes the crash.
Moving ConstructorHelpers out of the switch, to the beginning of the function also fixes the crash.

Hi ,

Your code appears to be fine. I tried to reproduce this myself, but was unable to do so. Does this only happen in your own project, or do you see this happen in a new project as well? Also, just to make sure, everything works fine the first time you play your BigGameMap level, but the second time you load the BigGameMap level this issue occurs? What is the exact error message that you see?

Yes, after level reload the problem occurs. I don’t have any error message, except critical error. And game crash.

Here is the log I figured out hat the reason is - WraithPlayerPawnBPClass and DomPlayerPawnBPClass ahve their values set to ‘None’, so DefaultPawnClass beacame None, and game crashes. And they are not repopulated, as they are static and where created long ago.

I removed static from them, so everything works ok now, But not sure if I am hiding some engine bugs. Can their values became obsolete somehow? Or they are collected by GC. Don’t know.

The problem produces only in packaged project. Running from UE is ok. So it was hard to find.

I still have not been able to reproduce the crash that you described. Are you performing your level reload through C++ or Blueprints? Could you provide the details for how you are reloading the level?

Sorry, , I was little busy. I’ll try to make a test project on this weekend.

Hi ,

I just wanted to check and see if this issue is still occurring. If so, I was wondering if you may have had an opportunity to create a sample project showing this issue. There is probably some small detail that I am overlooking.

Hi ,

Sorry for a delay. Here is a test project.

Test project

It is pretty simple. It collects garbage and loads new levels, while randomly selecting default pawns in game mode switch.

It works fine in Editor, to reproduce the error you should make a packaged build. Attach to it with a debugger, and you’ll see that ConstructorHelpers are reset to None.

Tested it with moving ConstructorHelpers out of the switch’s cast blocks to the beginning of the function also fixes the crash. Maybe I am missing something in c++ knowledge, nevertheless using static in switch blocks looks a little bit ugly.

Hi ,

Thanks for the sample project and additional clarification. I was able to reproduce what I believe is the issue you described. I did not see any problems the second time the level was loaded, but after several attempts reloading the level, it eventually crashed. Re-running the project and reloading the level multiple times again resulted in the same results.

It looks like what may be happening is that FClassFinder does not attach the found class to root, and the pointer to the class ends up getting cleaned up by garbage collection which results in what you were seeing. I entered a ticket for this issue (UE-22667). We have a potential fix ready to go in internally. It just needs to be tested and verified. For now, you can take care of this yourself by adding this line to each switch case: Character1BPClass.Class->AddToRoot();

You want to add that line inside the if statement of each case, before you set the DefaultPawnClass.