I am trying to store some commonly used, constant data, in a singleton object. These data are in the from of TAssetPtr. I am not sure if I really want all my singleton data to be persistent, raw pointers, so I am sticking with asset pointers for now, and loading them asynchronously. My issue is, I cannot find a good time to do the asynchronous loading.
I tried doing it in the constructor of the singleton or the class containing the data, but that causes a lot of crashes - I assume mostly because the order of instantiation of the singleton might propose some challenges. (i.e I couldn’t use the AssetManager when the singleton is constructed).
My current solution is such that whenever data is requested via the singleton, the singleton instance first verifies if all the assets were preloaded. If not, then it forces an async load before returning the request. This solution is rather hacky, because the async load will never finish on the same frame the request for the data was made. So I am left with few seconds where I receive null data before things fully initialize.
So the question becomes, what is a good place or entry point to do all loading I want?
Here is an example. Assume a singleton that contains a sound manager. The sound manager contains the actual asset pointers that require loading. The singleton’s get method looks as follows:
class USoundMgr : public UObject
{
void PreloadSoundAssets();
bool IsLoaded() const;
...
UPROPERTY(EditDefaultsOnly)
TAssetPtr<DataType> Data;
}
UBaseSingleton* UBaseSingleton::Get()
{
if(!GEngine)
{
return nullptr;
}
UBaseSingleton* singleton = Cast<UBaseSingleton>(GEngine->GameSingleton);
if(!singleton || !singleton->IsValidLowLevel())
{
// ("No Valid Singleton found!");
}
if(!singleton->SoundMgr->IsLoaded())
{
// ("Force Preloading Sound Manager!");
singleton->SoundMgr->PreloadSoundAssets();
}
return singleton;
}