I am trying to implement enemy drops. I have an actor component that is my “loot table” and it attached to “enemy” classes. The spawning of random items works great. The item is a class derived from AActor. When the items spawn they will sit in the world indefinitely but as soon as I pick them up into my inventory UE4 garbage collector deletes them. I have tried to create a pointer marked UPROPERTY in the loot table class that is set to point to the new spawned actor when it is spawned. I also tried to add that spawned item to a TArray of Item pointers that is also marked with UPROPERTY. Finally when I add the item to my inventory it goes into another TArray of Item pointers. I have also tried to SetLifeSpan on the newly spawned actor to 0 and something ridiculously high like 10000000. No matter what I do when pick up the spawned item it gets deleted by ue4.
Here is some of my code below:
Spawning item:
spawned_item declaration:

Tarray in gamemode class:
Tarray for inventory items:
AddItem to inventory method:
Does anyone know why my spawned actors here are being garbage collected as soon after I pick up the item?
Seems like it should work based on what you’ve shown but C++ is a fickle beast. Can you remove the UPROPERTY decorators and use a TSharedPtr instead? UPROPERTY should be doing that under the hood, but try doing it explicitly. If you need to access one of these objects from blueprint, write a wrapper function that returns the TSharedPtr as a raw ptr with MySharedPtr.Get();
How do I declare a TSharedPtr in my class, then inside one of that class’s methods spawn an actor, and assign my TSharedPtr to this newly spawned actor?
TSharedPtr<AItem> SpawnedItem;
AItem* Item = SpawnActor(ItemParams);
SpawnedItem = MakeShareable(Item);
Thank you!
Using the TSharedPtr didn’t prevent it from being deleted and then I got a read access violation crash after the item was destroyed. I did notice that the item only gets deleted when I add it to my InventorySystem’s Tarray of Items (this is an Actor Component class that I use for… inventory). I line trace for items from my player and if I have a blocking hit and hit the interact input (E) then the item hit by the line trace gets added to the inventory via a combo of these methods:
I’m not convinced it’s the functions themselves because when I pickup items that were placed in the editor (pre start game) those items never get deleted when I put them in my inventory. Do you think it has something to do with the TArray that I’m using to store the items for my player character? IT is marked with UPROPERTY as well
I may be off-base here, but I feel like it might make more sense to have an inventory item class which isn’t an AActor subclass. Since an AActor is, I believe, fairly inherently tied to “being in the world”, it feels like something that’s risky to hold onto once it’s removed from said world.
I’d probably make a different UInventoryItem
, and have your AItem
contain an instance of that. Then, rather than adding the AItem itself to anything, you’d just add the UInventoryItem it contained to your inventory instead. That way, it wouldn’t matter if the AItem that used to represent that inventory item as an object in the world went away or not.
1 Like
I had that same idea in the beginning. But I was under the impression actors were great for spawning at run time. I actually have it so my Item class is initialized by a struct with all the info an item would need. So in that sense I’m just spawning blank items and then populating them as needed.
I could try something like your suggesting and use the struct info to fill the item actor class with the data it needs and then when I add to inventory make a copy of that item and add it via a uobject subclass to my inventory.
It’s annoying though bc I feel like all the stuff I read about garbage collection seem to say actors and actor components are the exception to the garbage collection rule about being auto deleted bc they automatically get added to the root set and therfore don’t get deleted. I may be reading/understanding wrong though.
Actors definitely get GC’d, no exception there really. The way to prevent them getting GC’d is the same way you prevent UObjects and other GC-able objects from getting GC’d - you create a hard (read: shared) reference to the object. Sounds like something else is afoot in your specific situation but I can’t work out what.
Is there any way you can store these actors in a blueprint array instead of C++? All ptr variables in Blueprints are automatically protected from GC as long as the addresses are valid. So maybe you can have a BP inventory class that inherits from your C++ inventory class? Not at all ideal considering how you’ve built this, but it would at least help us all understand the issue here.
For testing purposes, this is how you would access the BP variable from C++ code: Access BP variable in C++ - #4 by andrea.b
I found a solution, and to be honest I don’t fully understand it yet. Maybe something to do with collision.
My item class had a staticmeshcomponent that is set as root of the object/(class?) in the class constructor.
The struct that stored the info for each item to be initialized at spawn had a static mesh that the staticmeshcomponents mesh got set to. I was using the 1M_Cube that was part of the default project. When I used that static mesh or any other base engine static mesh the spawn got GC after adding it to inventory. All the other static meshes I have used don’t get GC.
So yeah idk. Lol. 
Huh. Well. Note to ourselves, then 