How to iterate all assets in Folder without using the Asset Registry?

Hi, Guys

I want to iterate and load all assets in the Non-Editor (Game) mode, but the Asset Registry is editor subsystem. When I was using the Asset Registry in the Game mode, it cannot find and load the asset, and return a nullptr using the GetAsset() . it reports an UObjectGlobals warning failed to find object ... . However, in Editor mode, it works fine.
Could you please teach me how to load all assets in the folder without using the Asset Registry?
Thanks
Bests
YL

Hi ,

What you could do is, at edit time, create an object library. Object libraries are collections of objects that can use either weak or strong references, and can automatically populate itself with assets from paths for you. This will also allow “finding” your assets at run time to be much faster.

Hi, DarkwinRichard

Thank you for your help. May I ask a silly question? Does this UObjectLibrary can iterate and load all assets which are in the Folder in the disk? I have not used it before.

Thanks
YL

Hi ,

Yep! An object library is limited to a certain class (though this class can just be UObject if you so desire), but you can set whether or not it should recursively search paths you give it (by setting bRecursivePaths) and then load assets from multiple folders or a single folder. One thing to note, though, is that object libraries use the asset registry module to find the assets, so they must be created at edit time.

Hi DarkwinRichard,

Thank you! helps me a lot, but it is still have a question. You mentioned that the Object Library uses the Asset Registry,but as I know the Asset Registry is editor subsystem, and it cannot be used in Game Mode. So the Object Library can solve this problem and be used in the Non-editor mode?

Thanks
Bests
YL

Hi ,

Yes. The object library uses the asset registry to load the files and store them, which is why you must create it at editor time. You yourself will not need to add a dependency to the asset registry module. However, like I said, you must create the object library in the editor. You can then use it at runtime.

Hi ,

Yes, that can be done. Using a Blueprint function library implemented in C++, you can write a function to create the object library then save it in your game (see this question for an example of how to do that). From there, you can use a Blutility to call that function from the editor. There are several ways you could go about creating the object library, but that is the most straightforward way.

Hi DarkwinRichard,

Thank you for your immediately reply! Actually I am a newbie, I am confused about what you said " you must create the object library in the editor". How could I create it in the Editor and use it at runtime? Does that mean the editor branch? I want to coded it in C++ and run it in CI in game mode. Can it be achieved? Forgive my silly question.

Thanks
Bests
YL

Hi DarkwinRichard,

What I have encountered is that when I use the UObject* Object = Asset.GetAsset(); the asset is FAssetData in game mode, it shows that failed to find the object, but it works fine in editor mode. So When I create the Object Library in editor mode, and run it in the Game mode, it can load the assets as it does in the editor mode, right?
You really help me a lot!!! you are so nice!

Thanks!!
Bests!
YL

Hi ,

Why do you specifically need the asset data? FAssetData is part of the asset registry module, which means you cannot use it at run time (game mode, as you say).

And no. Object libraries load the objects at edit time, store them in a cached array, and only hold onto that array for use at run time. If you set your library to use weak references then you can access the objects using the WeakObjects property, otherwise you can use the Objects property.

Hi DarkwinRichard,

Thank you for your help! I need to explain in detail at first, my bad.

I want to use below code to spawn the actor at run time and then extract the static mesh and skeletal mesh and other information from it. So I met a problem that I cannot load the asset and reported Failed to find object... at run time by using the UObject* Object = Asset.GetAsset();,
So, I think it is maybe the problem of the AssetRegistry. Because of this, I just wanna another way to avoid this problem. As you said the Object Library is the way to solve this problem, do you know other way to solve this problem or avoid to load the asset and can extracts the mesh and other information from it? Really really thank you!

FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
TArray<FAssetData> ObjectList;

AssetRegistryModule.Get().GetAssetsByClass(UBlueprint::StaticClass()->GetFName(), ObjectList);
for (auto ObjIter = ObjectList.CreateConstIterator(); ObjIter; ++ObjIter) {
const FAssetData& Asset = *ObjIter;
UObject* Object = Asset.GetAsset();
UBlueprint* BP = Cast<UBlueprint>(Object);
UClass* AssetClass = BP->GeneratedClass;
FTransform Transform;
FActorSpawnParameters SpawnInfo;
auto World = GEngine->GetWorldContexts()[0].World();
AActor* Actor = nullptr;
if (AssetClass->IsChildOf(AActor::StaticClass())){
Actor = World->SpawnActor(AssetClass, &Transform, SpawnInfo);
}
}

Thanks
Bests
YL

Hi ,

As I have mentioned before, you cannot use FAssetData at run time because it is part of the asset registry module. You cannot use the code you have posted while your game is running. Once you have created your object library, your code that you posted would look something like this:

TArray<UBlueprint*> BlueprintList;
MyObjectLibrary.GetObjects(BlueprintList);

for (UBlueprint* BP : BlueprintList)
{
	UClass* AssetClass = BP->GeneratedClass;
	FTransform Transform;
	FActorSpawnParameters SpawnInfo;
	UWorld* World = GEngine->GetWorldContexts()[0].World();
	AActor* Actor = nullptr;
	if (AssetClass->IsChildOf(AActor::StaticClass()))
	{
		Actor = World->SpawnActor(AssetClass, &Transform, SpawnInfo);
	}
}

Hi DarkwinRichard,

Thank you for your help! I got it! Thank you very much!

Thanks
Bests
YL