I’m working on an inventory system where each item is defined by a struct that contains metadata like the item’s name, description, mesh, and a soft reference to a class (e.g., for spawning a medkit actor).
At BeginPlay, I use “Async Load Class Asset” (Blueprint node) to load the class. However, I do not store the loaded class anywhere — I simply run the async load. Then, at any point in time, the player can choose to consume the item, and at that point I spawn an actor from the class.
So far, this works. But I’m wondering:
If I don’t store the loaded class in a variable after async loading it, can it be garbage collected later?
Or does the async load automatically keep it in memory until the class is used?
Is there a way to check whether a specific class is still loaded in memory during runtime?
Should I be caching the loaded class reference myself to ensure it doesn’t get unloaded before the player uses it?
Anything else I should know about managing asset lifetimes with soft class references and async loading?
i don’t know, but that’s something i’d like to know. i’ve search it before but couldn’t find any info.
i usually only load things i use. but sometimes i need to preload stuff.
potentially..
with tsoftobjectptrs you can call Get and if it returns nullptr then it’s not loaded. im not sure for bps.
i’ve found that a referenced object by tsofobjectptr, when it gets loaded by a datalayer, then the softobjectptr gets populated automatically. i’m not sure it will happen in other cases, but it might.
have you done some tests?
you can force trigger a garbage collect.
on a second thought:
if you are going to load the class when you load the item.
and you want to keep the object in memory.
then don’t use softpointers, since you’re basically doing the opposite of what they are used for.
just use simple tobjectptr.
Hey thanks for the response. Glad I’m not alone here. So I ran Obj GC which I found online that should run the garbage collector using the terminal. The reason I have soft references in the first place is because I have a large data table of items that all contain an actor class (and some other references to objects) that don’t always need to be loaded in. But for now, I load in the class because I’d imagine that if the player wanted to use a consumable, it might suck if they’d have to wait to load the item in. However, I can see an argument that the load time would be so quick that it wouldn’t really make a difference to load it in when they want to use the item (like a medkit or something like that). I’m not really sure what the better approach is for that. I’m only preloading in items that the player would be using at any point like what is in their currently equipped bar and things like that.
Oh i see why.
Well it reolly depends to be honest.
You might as well end up with a lot of loaded assets just because someone has many items on their inventory.
And it really depends on those classes and how they are engineered.
If the load is async, then it would be fine to load only when used. in theory you would not notice.
The problem with async is that… its async.
So if your inventory is some sort of plugin you will need to expose a way to be notified of the asset being ready.
And that makes the code harder.
For your words im assuming you are making a plugin for other people to use.
I can only give you my opinion, but its just an opinion.
Id prefer preloading when you obtain the item.
To make the code easier.
But the issue with that is you can still get into the situation where the user would want to do something with the item immediately after obtaining it.
So you will still end up having to support a notification.
Another posibility is maybe leave the loading to the user. They can preload if they want, and also bind to some delegate otherwise.
So I’m actually building my inventory and all of my systems myself since I do have a strong programming background fortunately. Currently, the plan is to just load in items that have the potential to be used (but loading in all of the items that get added to the inventory wouldn’t be too cray since it’s a fixed size of about 30 items). I’m just more concerned about how long those items stay loaded in without a direct reference to them. Because currently, it works. But I don’t know how long they stay loaded in and what causes them to be unloaded. Usually things tend to get unloaded when either explicitly destroyed, or don’t have any hard references anymore. But this is a class reference too so I don’t know what’s holding its lifetime.
like i said i don’t have the answer, and i’m interested in that too.
i think the only way to know is to try it out. (while you wait for someone who do knows to show up, but i find it unlikely and untrustworthy by my experience).
set up a case, and run some tests.
force the gc a few times. if they don’t get unloaded, then they don’t.
go with that solution for some time and add some logs in case they get unloaded and keep an eye on it.
tangential, but if you allow me to share my opinion.
i’ve found really helpful to try to restrict myself to the things i need in the moment, and don’t try to code for things i don’t need right now.
it might seem counter intuitive, but it actually proved to be extremely efficient.
even considering sometimes you need to do some refactoring.
it does not means not thinking about the best way or try to future proof it, but only without going out of your way.
i used to do it the other way, and a few years ago started doing this way, and it proved to be much better.
but, ymmv. just sharing my experience.
@nande I really appreciate your insights. I did run a few Obj GC commands and waited a moment too and haven’t noticed a problem so I’m not sure what keeps track of the lifetime. But I can definitely move things around to load items in only when they’re needed since it probably isn’t that big of a deal on performance (in a noticeable way). Hopefully we both get our curiosities answered!
if its just meta data like name you have it in the struct or data asset,
if for spawning like dropping an item then a slight delay for async load probably isnt an issue.
if its something like use medkit you dont need to spawn it all, you could have an execution class like a UObject thats lightweight and would basically load instantly
Some of the items can be weapons and consumables and stuff like that so I would need them to be tied to that and spawn them in whenever needed. I just wanted to do it the most seamless way for the user while still remaining efficient.