Reference being added to defaults container

I’ll get right to it: I have a custom UActorComponent that handles the player’s actions (queuing actions, checking if an action can be executed at the moment, all that stuff) which has an array of UAction pointers (these inherit from UObject) which are the actual actions themselves (they mostly just store data about the action). When I wish to add an action, the UAction is spawned, a pointer is sent to the ActorComponent, checked, and if it is possible, the pointer is added to the array in the ActorComponent. This is all standard stuff, the function to add it to the array is a simple Array.Add() (at least it is now after I stripped away everything looking for a possible source of the issue) in C++ (called via BP), so I’m nothing fancy here.

Just to be thorough I’ll post the code of the function:

// .h

//This is the array
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Actions|Status")
TArray<UActionObject_Masterclass*> ActionList;

//This is the function, called via a wrapper function that is exposed to BP
void AddAction(UActionObject_Masterclass* ActionRef);

// .cpp
void UCreatureActionHandler::AddAction(UActionObject_Masterclass * ActionRef)
{
	ActionList.Add(ActionRef);
}

Here is the problem: for some reason, these elements are not only added to the instance of the component in the world, but also to the BP class itself, and once I end Play In Editor, these elements will show up in the Blueprint Defaults of the class in question (the pointers are null, so it’s just a lot of null references in the array, very annoying since they are still seen as elements and will crash the editor even with range-based for loops when it tries to access one).

Image of the component’s defaults after PIE:

224441-defaults.jpg

I have am at wits end for this, at first I thought it would be some sort of CDO issue, but having put a check for CDO before the action was added (it didn’t solve the issue), I do not know what the problem is, it seems to be somehow calling the function to add the reference to the class itself.

Weird. The session you run affects the blueprint after it’s finished?

I don’t know what that’s about but one possible work-around is to clear the array on EndPlay.

Yes, that seems to be what is happening. Somehow it is added to the defaults and persists after PIE. I have thought of clearing the array manually but it seems like it shouldn’t be needed, I assume this behaviour is intended since I can’t find anyone else with this problem (I don’t think UObject* arrays are rare, so someone else must have encountered this), in which case I’m sure there must be some way to avoid it.

Come to worst I’ll clear the array manually on end play, however it would be interesting to know what is causing this since as far as I know changing BP defaults at runtime requires quite a lot more work than that, and other arrays in other classes don’t have this issue (perhaps it’s something to to with arrays in UActorComponents, perhaps with UObjects, perhaps both of them together).

Defaults are supposed to go back to default when the play session ends. Or, I’ve been very mistaken about how UE4 works. You aren’t adding anything in your constructor or the constructor of a parent?

If you can, you might want to reproduce the problem in an example project so we can take a look.

Nothing is being done in the constructor apart from enabling tick (bCanEverTick = true), and the component inherits from UActorComponent so the issue is (probably) not in the parent constructor either. It’s especially weird since the UObjects themselves are obviously being deleted after PIE (hence the nullptrs in the array), yet the elements themselves in the array remain.

I will make an example project to reproduce it later today when I get home.

And you’re sure you’re not adding to the class’ default object? Not even sure that’s possible but it’s the only other explanation I can think of that doesn’t involve a bug.

I’m as certain as I can reasonably be, I put in some checks for CDO flags to stop the CDO from doing anything but that did not help (it also never returned true for the CDO flags, so it doesn’t seem like the CDO is getting a call at all). I tried making an example project but the issue was not present (I have quadruple checked that everything that could affect it was the same).

What’s more, my component has now become null. This is not the first time it happens, suddenly for no discernible reason a UActorComponent will become null (getting it from BP returns null, and selecting it in the hierarchy just shows a completely blank defaults tab) even though nothing in the logic for adding it was changed (doubly sure of this since I use Perforce and the actor that has the component spawned and attached has not been checked out). Before I thought this issue was a bug with the C++ delegates (last time it happened was when I added multicast delegates to the component) but it now happened out of the blue. If I were to hazard a guess I would say that the construction of the UActorComponent fails and causes:

//creature .cpp
CreatureActionHandlerComponent = CreateDefaultSubobject<UCreatureActionHandler>(FName("ActionHandler"));

to assign a null to CreatureActionHandlerComponent, but I can’t say for sure.

I don’t really know what the issue is right now so I will do some testing and report back once I start getting a clearer picture, it might be that this defaults bug is just a symptom of a root cause (which also causes this bug with the component going null). The problem is that it is so sporadic I can’t really pinpoint the change that causes this to happen, all I did between the time the component was fine and when it started returning null was refresh code files and rebuild in VS.

Oh good it gets worse… :slight_smile:

I don’t know if it’s necessary but all the examples I’ve seen have the sub-object name (in the quotes) set to the same name as the variable being assigned. Maybe having a different name in quotes is confusing the GC?

Maybe something got corrupted. I would delete all the intermediate directories and build from scratch. Have you tried that?

I have tried changing the name to be the same as the variable, but that did not help. I also deleted the intermediate, binary, and saved directory as well as the solution and regenerated it, then rebuilt from VS and finally started UE4, that did not help either.

I have noticed one thing however: If I in any way touch the component variable (change UPROPERTY specifiers or change the name for example) it is temporarily “fixed”. I can access it from the defaults however rebooting the editor will once again turn it null and playing in editor will spam errors about it retrieving null from the get component calls in BP (so really it isn’t fixed at all). Last time I had this problem I fixed it by changing the variable name itself, though it seems like it was only a temporary fix and evidently the root cause has to be solved this time.

Thanks for the help, I’ll do some more testing and prodding but if the issue persists I should probably make a new thread as the issue is completely separate from what it initially was (perhaps it’s the same root cause though) and takes priority since I can’t really try to fix an issue inside the component when the component itself is completely broken.

Found the root cause: UPROPERTY seems to be causing some malfunctions for the UActorComponent, removing the UPROPERTY from the variable declaration and using a getter function to get a reference to it seems to have fixed the issue. It is not a perfect fix but it will have to do.

I will make a bug report as best I can later today (considering it is very sporadic and hard to replicate), in the meantime I will mark this post as answer in case someone else with the same issues stumbles upon this.