Async Loading Multiple Assets: How to Keep Order With Null Object Paths?

Hello!
I’m trying to solve a problem with async loading that I’ve had for awhile now. When appropriate, I like to use RequestAsyncLoad with a TArray of FSoftObjectPaths (e.g. loading particles and sounds together since they play at the same time, or loading multiple materials that will be applied to the same object).

However, in some situations, certain assets I go to load may end up being null. For instance, let’s say I have an actor that plays a particle effect and/or a sound cue on overlap. Some child classes of this actor may not play any particle effects, and may only play the sound cue. When the load is complete and the delegate function is called, GetLoadedAssets() would only have 1 asset in the array – which is correct. But what would be the best way to determine that asset is the sound cue, and not the particle effect?

In this situation, I could simply brute-force casting. However, the issue becomes more apparent when you have an ordered list of asset paths you want to load in an exact order – some of which may be null.

For instance, a mesh that may have 5 materials that need to go in 5 specific slots. But material 2 and 5 might sometimes be null. Once the materials finish loading, GetLoadedAssets() may have 3 assets, but as far as I can tell it seems impossible to determine that materials 1, 3, and 4 were the ones loaded. All three loaded assets derive from UMaterialInterface, meaning that I can’t brute-force a solution by casting.

The way I’ve found around it is to just make FStreamableHandles and “OnLoaded” functions for each asset I want to load, but this gets bloated really quick – especially in the case of the second example.

I tried passing in dummy paths if an asset is null, but it seems that the StreamableManager throws those out.

Does anyone have any suggestions to keep asset paths in order when async loading with null paths?

Once RequestAsyncLoad completes, reuse your original TArray of FSoftObjectPaths instead of using GetLoadedAssets() from the request. Use SoftObjectPath.ResolveObject() to access the loaded object.

Also keep in mind RequestAsyncLoad() will throw an error and cancel the request if there are zero assets to load. So you’ll need to put code in front to make sure you have at least one non-null before calling it.

2 Likes

Not sure why I never thought of just storing an array of the FSoftObjectPaths… That’s a wonderful suggestion! Thank you very much! :slight_smile: