C++ UPROPERTY actor component variable being set to null

I posted another question here https://answers.unrealengine.com/questions/737973/reference-being-added-to-defaults-container.html which is likely related and sharing the same root cause.

In short, I have a custom UActorComponent called UCreatureActionHandler (to handle actions as objects determining what is currently being done and what can and cannot be done by my character) being added to my custom ACharacter class, and using the UPROPERTY specifier in the variable declaration seems to cause sporadic, hard to track issues (mainly the component being null in BP, but also the above linked bug).

My code is as follows:

//In ABaseCreature_Masterclass.h
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Components") //This line is the problem
UCreatureActionHandler* CreatureActionHandlerComponent;

//ABaseCreature_Masterclass.cpp
ABaseCreature_Masterclass::ABaseCreature_Masterclass()
{
	PrimaryActorTick.bCanEverTick = true;
	CreatureActionHandlerComponent = CreateDefaultSubobject<UCreatureActionHandler>(FName("CreatureActionHandlerComponent"));
}

The component UCreatureActionHandler is a simple C++ component inheriting from UActorComponent with default constructor, tick, and beginplay that comes with the class (there is more code but I commented everything out in the process of trying to find what was causing the bug, with no luck). As it stands now, the component does not have anything added to it that could cause an issue.

The problem presents itself in the form of the CreatureActionHandlerComponent variable being null. In the Blueprint defaults the window will be empty and blank when the component is selected and trying to get a reference to it via BP will return nullptr. However the component itself is working and present (e.g. printing from its tick function will show up), but the variable in the character is wiped clean.

A few quirks I have noticed:

-Changing the name of the variable will temporarily fix it (has lasted several weeks before) but it will break again whenever changes are made (exactly what changes I am unsure of)

-Changing any specifiers of the UPROPERTY in the variable declaration will temporarily fix it (usually until the next engine restart)

-Seems more prone to breaking if delegates are added, removed, or altered (altering delegates may also fix it until next compile/restart)

If I remove UPROPERTY from the variable declaration in ABaseCreature_Masterclass.h the component will work fine (but not be blueprint accessible in the same way, of course). This is a temporary fix that works but is not ideal since it makes it more annoying to work with the component. I have also noticed that I am not alone having this issue: Unreal Engine Issues and Bug Tracker (UE-18284) is similar (though mine is not caused by a class change) and https://answers.unrealengine.com/questions/734317/custom-uactorcomponent-is-null.html who also found that removing UPROPERTY fixed the issue.

I have tried replicating this in a fresh project but I have had no luck with it (which is why I didn’t post this as a bug report). However I have quadruple checked everything and there is no code affecting this component and its variable in the character that is not present in my replication attempts. While I could migrate the entire project to a new blank slate, it would be quite cumbersome not to mention there is no telling if the issue may return in the near future or not regardless.

I have tried basically everything by now, and while I could circumvent this issue by removing the UPROPERTY specifier it also makes it considerably more annoying to work with delegates in the component.

3 Likes

Encountered the same issue on UE4.21.1.

It seems UPROPERTY is indeed the culprit here.

For me having changed UPROPERTY(BlueprintReadOnly) to UPROPERTY(EditDefaultsOnly) seemed to have worked for my Actor Component.

Before, whenever I would reference the Actor Component from a deriving Actor Blueprint, it would throw an error, saying the component is dereferenced e.g: Accessed None trying to read property MyComponent.

This is just speculation on my part, but it might be that setting UPROPERTY makes the component prone to garbage collection, especially when the component is mostly empty or has a few print calls.

Not sure if fully related, but I found that using “VisibleAnywhere” in place of “EditAnywhere” will allow the component to show up in the blueprint editor.

Thanks, both of you seem to be correct, marked it as answer since this seems to be the only way around it for the time being.

This worked for me (Using EditAnywhere). This started happening randomly, seems to be some kind of issue related to the blueprint corruption when inheriting from a C++ class.
I realized this, because if I created a new BP inheriting from the same class, it was fine (But didn’t want to use this approach).

The way I finally solved this was by replacing VisibleAnywhere with EditAnywhere as stated by @Dune but I think what this actually did was somehow “fix” the corrupted BP to work as before.

Hope this helps someone, because I looked for solutions online for a few hours and there was no clear answer, I guess this is an Engine bug.

I am using UE 4.23.0

I am not sure how to tag a dev from Unreal Engine here but maybe an option to “refresh” the blueprint class could solve this.

2 Likes

For me ended up being null in BP when using either BlueprintReadWrite or BlueprintReadOnly regardless of other tags, what I did is UFUNCTION(BlueprintPure) getter instead as a workaround.

I had the same problem, but changing tags in the UPROPERTY did not fix it. I ended up having to change the name of the component variable.

PlayerEquipment = CreateDefaultSubobject<UEquipmentComponent>(TEXT("PlayerEquipment"));

to

PlayerEquipment2 = CreateDefaultSubobject<UEquipmentComponent>(TEXT("PlayerEquipment2"));

Very strange bug, and a pain to deal with.

Apparently it’s also null in c++ at random… renamed it like the guy below and hope for the best.

That partially fixed the issue for me, it worked in standalone, but not in the editor.
But after I closed the editor, deleted all files in ProjectFolder/Build/Win64, and opened the editor, it seems to work again.
thanks.

Had to deal with the same issue in 4.25.4. Adding a second component in c++ somehow corrupted already added custom actor component. VS debugger shows that component is created but after loading the blueprint it doesn’t show the details panel and appears as a null component. Remove the c++ parent and re-added it again to the same blueprint fixed the issue.

Was dealing with this all day, but I was able to fix it by adding , meta = (AllowPrivateAccess = "true") to the UPROPERTY of the Component reference

1 Like

Also having this issue in 4.27. This happens with all components that are initialized from C++ in the constructor. I find that when attempting to play in editor, these components are null when begin play happens. I’m unsure how to fix this at the moment, but I will update here when I have found a work around.

1 Like

This is most likely due to the behavior of uobject construction to set UPROPERTY variables to a copy of the “archetype” object from GetDefaultObject for the class. This happens AFTER the C++ constructor is called. In my case, I had runtime-created UTexture2D objects as UPROPERTYs so they wouldn’t be garbage collected, but the variables were being set back to nullptr right after the constructor.

This may differ depending on how the object is constructed. The object in my case is an actor in a level. I haven’t solved this yet but I’m assuming there’s a UPROPERTY specifier that will will change this. The bCopyTransientsFromClassDefaults value below is false.

// UObjectGlobals.cpp FObjectInitializer::PostConstructInit()
// UE 5.4.4
	if (bShouldInitializePropsFromArchetype)
	{
		UClass* BaseClass = (bIsCDO && !GIsDuplicatingClassForReinstancing) ? SuperClass : Class;
		if (BaseClass == NULL)
		{
			check(Class==UObject::StaticClass());
			BaseClass = Class;
		}
	
		UObject* Defaults = ObjectArchetype ? ObjectArchetype : BaseClass->GetDefaultObject(false); // we don't create the CDO here if it doesn't already exist
		InitProperties(Obj, BaseClass, Defaults, bCopyTransientsFromClassDefaults);
	}

Additionally, my case seems to be related to the fact that I am in fact using a BP subclass of my C++ class, which may not properly inherit changes to UPROPERTYs or other things that have had edits in the BP which override.