My setup is as follows:
I press a button on my widget to try a hero:
void UHeroInfoWidget::OnTryHeroButtonPressed()
{
UTBCGameInstance* GameInstance{GetGameInstance<UTBCGameInstance>()};
_LIKELY if (GameInstance)
{
GameInstance->SetPlayerCharacterClass(HeroInfo.CharacterClass.Get());
GameInstance->AsyncLoadMap(TryHeroLevel);
}
}
It asynchronously loads TSoftObjectPtr TryHeroLevel map:
void UTBCGameInstance::AsyncLoadMap(const TSoftObjectPtr<UWorld>& Map, const bool bShowMapAfterLoad)
{
const FLoadPackageAsyncDelegate LoadDelegate{
FLoadPackageAsyncDelegate::CreateUObject(
this, &UTBCGameInstance::OnAsyncLoadMapCompleted, bShowMapAfterLoad)
};
LoadPackageAsync(Map.GetLongPackageName(), LoadDelegate, PKG_ContainsMap);
}
void UTBCGameInstance::OnAsyncLoadMapCompleted(const FName& PackageName, UPackage* LoadedPackage,
const EAsyncLoadingResult::Type Result,
const bool bShowMapAfterLoad) const
{
if (Result == EAsyncLoadingResult::Succeeded && bShowMapAfterLoad)
{
UGameplayStatics::OpenLevel(this, PackageName);
}
}
It works as intended, main game thread doesn’t lock, nothing freezes.
However, I face a problem when trying to enter a TransitionLevel while TryHeroLevel is loading.
If I add a OpenLevel synchronous function in widget like so:
void UHeroInfoWidget::OnTryHeroButtonPressed()
{
UTBCGameInstance* GameInstance{GetGameInstance<UTBCGameInstance>()};
_LIKELY if (GameInstance)
{
GameInstance->SetPlayerCharacterClass(HeroInfo.CharacterClass.Get());
UGameplayStatics::OpenLevelBySoftObjectPtr(GetWorld(), GameInstance->GetTransitionMap());
GameInstance->AsyncLoadMap(TryHeroLevel);
}
}
my main thread freezes, I see transition map for a slight moment before being moved to TryHero level. I’m not sure how to handle this correctly besides just adding TransitionWidget on screen and not moving to TransitionLevel. Any insights?