If i hit the play button in the editor, everything works just fine. FAssetRegistry finds and lets me load StaticMeshs, Materials and Blueprints without a problem.
But as soon as i launch the game or package and run the exe, the blueprints cannot be loaded anymore.
Asset discovery code still finds the blueprints:
Filter.PackagePaths.Empty();
Filter.PackagePaths.Add(FName("/Game/LevelCreator/Objects/Dimension1/Biome1/Lights"));
MeshAssetList.Empty();
AssetRegistryModule.Get().GetAssets(Filter, MeshAssetList);
And i load them with this:
template <typename ObjClass>
static FORCEINLINE ObjClass* LoadObjFromPath(const FName& Path)
{
if (Path == NAME_None) return NULL;
//~
return Cast<ObjClass>(StaticLoadObject(ObjClass::StaticClass(), NULL, *Path.ToString()));
}
On launch i then get log entries like this:
[2015.04.11-15.32.47:804] 0]LogUObjectGlobals:Warning: Failed to find object 'Blueprint /Game/LevelCreator/Objects/Dimension1/Biome1/Lights/FluorescentBar.FluorescentBar'
I packaged the game without using pak files and checked, the file was where it should be.
All my blueprints are derived from Actor and have a static mesh and a point light in them.
Are blueprints not useable in packaged/launch mode via dynamic asset loading?
I really like the bp’s to create small assets which i (hopefully) can spawn at different locations.
Rama
(Rama)
April 11, 2015, 10:43pm
2
UObjectLibrary
Have you checked out the UObjectLibrary class?!
It let’s you load blueprints!
UObjectLibrary
/** Load an entire subdirectory of blueprints into this object library. Only loads blueprints of passed in class. Returns number of assets loaded */
virtual int32 LoadBlueprintsFromPaths(const TArray<FString>& Paths);
Rama
Found the cause
Hi Rama
looking at its source it relies on EngineUtils::FindOrLoadAssetsByPath.
And now i know why it isnt working.
In Editor mode you can load blueprints with EngineUtils::FindOrLoadAssetsByPath(path, array, EngineUtils::ATL_Regular) .
This does NOT work in launch mode.
You have to load the class (EngineUtils::ATL_Class)
This was really annoying and very time consuming.
**Reminder to EPIC: **At least put in some Warning in if a function behaves differently from edit mode. Then we can find the cause sooner.
But i got it running.
template <typename ObjClass>
static FORCEINLINE ObjClass* LoadBlueprintFromPath(const FName& Path, const FName& BlueprintName)
{
if (Path == NAME_None) return NULL;
FString cName = BlueprintName.ToString().Append(FString("_C"));
TArray<UObject*> tempArray;
if (EngineUtils::FindOrLoadAssetsByPath(*Path.ToString(), tempArray, EngineUtils::ATL_Class))
{
for (int i = 0; i < tempArray.Num(); ++i)
{
UObject* temp = tempArray*;
if (temp == NULL || (!Cast<ObjClass>(temp)) || (temp->GetName().Compare(cName) != 0))
{
continue;
}
return Cast<ObjClass>(temp);
}
}
return NULL;
}
It defies the template approach, since its always a UBlueprintGeneratedClass, i know.
With a LoadBlueprintFromPath<UBlueprintGeneratedClass>() you can then spawn them with a GWorld->SpawnActor().
Thanks Rama, you got me on the right track
2 Likes