By default, Unreal is greedy in the way it loads assets, so when you access a UObject, all of its dependent resources are usually in-memory. For example, it's possible to access the texture associated with a
It's also possible to access
TSubclassOf<T> variables and call
GetDefaultObject() without worrying about whether the default object is in-memory.
Sometimes, however, this greedy-loading can work against us. Huge assets can be loaded when they are not needed, increasing our loads times and memory footprint.
The way to stop assets being loaded automatically is to use
To understand how to use both of these, let's go through an example.
Defining Our Data
For example imagine you are making a farm simulation game, and your growable plant properties are defined in inside Blueprint subclasses of
UPlantDefinition. Every plant has a large 1024x1024 pixel illustration that is viewable in an optional "details view" for each plant. It doesn't make sense for this texture to be loaded when the game starts, as it's almost never seen. Also if the game has tens of plant types the textures can really impact memory footprint and load times.
Instead our UPlantDefinition class definition would look like this
Asynchronously (and synchronously) loading data is supported in both Blueprints and C++. Blueprints is a little easier:
The asset returned by Load Asset is a plain UObject so we must cast it to our expected type.
Life in C++, as always, is a little more interesting.
In order to load our
TAssetPtr<T> resources, we need an instance of FStreamableManager that sticks around. There are a bunch of places you could put this instance, and to be honest I'm not 100% sure where is the "best". You could put it inside GameInstance, a custom game singleton, maybe even GameState.