Today I tried upgrading to 5.1 and after fixing some minor errors in code due to deprecated functions I managed to get it compiling and starting. Problem: As soon as the editor window pops up the whole thing freezes. 0% CPU utilization in the task manager. There’s nothing in the logs either. After some digging I found out that it must be some asset that can’t be loaded because if I start without contents it loads. Does anyone have an idea how I can track this down? Removing the folders one by one is going to take ages, there are tens of thousands of folders/files.
So after some more digging I found that not only one file is the problem. From AnimNotifies to skeletons everything’s broken. Some work, some don’t. Completely arbitrary.
Okay so I found the issue. One of my plugins is causing the issue. In particular a function call to UEditorAssetSubsystem::DoesAssetExist().
My code
bool UFoliageSimulationLogic::LoadGeneralSettings()
{
FString Path = "/FoliageSimulation/GeneralFoliageSimSettings.GeneralFoliageSimSettings";
// Check if asset exists
// This can return false if called directly after the engine is loaded up
if(UEditorAssetLibrary::DoesAssetExist(Path))
{
auto GeneralSettings = LoadObject<UGeneralFoliageSimSettings>(nullptr, *Path);
if(GeneralSettings != nullptr)
{
AssetDataLocation.Path = GeneralSettings->AssetDataLocation;
return true;
}
}
return false;
}
Engine Code in 5.0
bool UEditorAssetLibrary::DoesAssetExist(const FString& AssetPath)
{
TGuardValue<bool> UnattendedScriptGuard(GIsRunningUnattendedScript, true);
if (!EditorScriptingUtils::IsInEditorAndNotPlaying() || !InternalEditorLevelLibrary::IsAssetRegistryModuleLoading())
{
return false;
}
...
}
Code in 5.1
bool UEditorAssetSubsystem::DoesAssetExist(const FString& AssetPath)
{
TGuardValue<bool> UnattendedScriptGuard(GIsRunningUnattendedScript, true);
if (!EditorScriptingHelpers::CheckIfInEditorAndPIE() || !UE::EditorAssetUtils::EnsureAssetsLoaded())
{
return false;
}
...
}
The newly added EnsureAssestsLoaded() call seems to be the real issue here.
bool EnsureAssetsLoaded()
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
if (IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); AssetRegistry.IsLoadingAssets())
{
// Event is used like a condition variable here
UE::FLazyEvent AssetRegistryLoadEvent{EEventMode::ManualReset};
FDelegateHandle DelegateHandle = AssetRegistry.OnFilesLoaded().AddLambda([&AssetRegistryLoadEvent]
{
AssetRegistryLoadEvent.Trigger();
});
// open some message here
AssetRegistryLoadEvent.Wait();
AssetRegistry.OnFilesLoaded().Remove(DelegateHandle);
}
return true;
}
Inside of EnsureAssetsLoaded() the call to AssetRegistryLoadEvent.Wait() just pauses the game thread indefinitely.
Does anyone know a fix to this? An alternate function maybe?
I really wouldn’t worry about testing if it exists - LoadObject will return a nullptr if it doesn’t…
Well I fixed it by just checking if the asset registry has finished loading before even calling DoesAssetExist() but removing the check altogether is better I guess. Thanks! But I really don’t know why we wait for the loading to finish in EnsureAssetsLoaded() because unless you call it from another thread it will always block the game thread and thus will never finish loading the registry