UE5 Updating Field of an UActorComponent by Superclass doesn't Change the Field Value

Hey, I invoke a method of a UActorComponent by a SuperClass of the owning Actor. The method is actually called and is supposed to update a private field of the component. But this does not work.

I have created the following minimal szenario to show what I am stuggeling with.

There is a SuperClass called SuperCube derived from APawn.
In BeginPlay() the class gets a reference to UCubeComponent which is derived from UActorComponent.
The class SuperCube has an boolean IncreaseTestIndexClass which I can set to true in the editor. Each Tick checks if this boolean is set to true. If so, the SuperCube invokes the Method IncreaseTestIndex() from the reference of the UCubeComponent.

.cpp

#include "Units/SuperCube.h"
#include "Units/CubeComponent.h"

ASuperCube::ASuperCube()
{
	PrimaryActorTick.bCanEverTick = true;
}

void ASuperCube::BeginPlay()
{
	Super::BeginPlay();

	CubeComp = FindComponentByClass<UCubeComponent>();
}

void ASuperCube::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (IncreaseTestIndexClass)
	{
		IncreaseTestIndexClass = false;
		CubeComp->IncreaseTestIndex();
	}
}

The Code of the UCubeComponent is shown below. The Method IncreaseTestIndex() increases the private field TestIndex by one. Each Tick, the componend prints the value of TestIndex to log.

.cpp

UCubeComponent::UCubeComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
	SetComponentTickInterval(1.0);
}

void UCubeComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	UE_LOG(LogTemp, Warning, TEXT("Tick: TestIndex is: %d"), TestIndex);
}

void UCubeComponent::IncreaseTestIndex()
{
	TestIndex++;
	UE_LOG(LogTemp, Warning, TEXT("Updating TestIndex to: %d"), TestIndex);
}

Finaly I have create a BlueprintClass that uses the SuperCube class as parent class and added the Component to the BlueprintClass. As you can see in the following picture.
DetailsPanel

As you can see in the output Log (picture below), after setting the IncreaseTestIndexClass boolean to true, the method IncreaseTestIndex() of the component gets called by the super class. The value of the field TestIndex is actually changed and printed to the output log.
But the new value of the field is not used while printing the value of Testindex by the component tick. Why not? It seams like it uses to different instances of the UCubeComponent.

OutputLog

Silly suggestion…have you tried using GetComponentByClass versus FindComponentByClass. I don’t have the code in front of me so I can’t see what the implementation differences might be (assume one uses the other) but I can see that the signatures of the two functions are slightly different…

virtual UActorComponent * FindComponentByClass
(
    const TSubclassOf< UActorComponent > ComponentClass
) const

…versus…

UActorComponent * GetComponentByClass
(
    TSubclassOf< UActorComponent > ComponentClass
) const

Maybe there’s more than meets the eye under the surface.

Hey, thanks for replying.

I have tried

CubeComp = Cast<UCubeComponent>(GetComponentByClass(UCubeComponent::StaticClass()));

and also tried:

TArray<UCubeComponent*> CubeComps;
	GetComponents(CubeComps);
	if (CubeComps.Num() > 0)
	{
		CubeComp = CubeComps[0];
	}

It is always the same trouble.

I have found out, that it changes the address of the UCubeComponent which ticks. I dont know why.

WTAF?! That doesn’t seem good. Let me ponder…

Ok, so I can’t help but think something weird is going on between cpp and bp interaction. Meaning, I can see that you have sub-classed ASuperCube within BP and added the component in BP. Then in cpp, you’re trying to access that component and use it. Not that I think you shouldn’t be able to do that, just that maybe there’s an extra step needed to make that happen that was missed. Is there a reason you didn’t add the actor component to the super class (ASuperCube) from the get go within the constructor?

EDIT: Would be interested to see if calling IncreaseTestIndex from within your bp would make a difference.

Calling IncreaseTestIndex() from within the Blueprint causes also a change of the Address.

It seams that calling the IncreaseTestIndex() from the BP creates a new instance and hence resets the value of TestIndex to 0. After that it increases the value to 1 and prints that new value during the tick.

OutputLog_3

Still not understanding what is going on.

I am going to test if adding the component within the constructor will change anything. But I do not think so.

Interesting, so at the very least the change is reflected so we’re edging closer. Out of curiosity, how are you flipping the boolean flag?

EDIT: Also, how did you add the component in BP? Did you just add it via the editor preview panel or are you adding in the constructor or begin play?

The boolean is a UPROPERTY with EditAnywhere

UPROPERTY(EditAnywhere, BlueprintReadWrite , Category="Test Parameter")
		bool IncreaseIndexClass = false;

and I change it in runtime thorugh the editor as shwon below:
DetailsPanel_2

I added the component via the Blueprint Viewport. Not in runtime using BeginPlay(). But this should not be the problem.

The change of the ComponentAddress only happens, if I use the GameEditor to set the IncreaseTestIndexClass boolean to true.

When I modify the Tick(…) method of the SuperCube Class like:

tickSum += DeltaTime;

	if (tickSum >4)
	{
		tickSum = 0.0;
		CubeComp->IncreaseTestIndex();
	}

That way it calls the IncreaseTestIndex() of the UCubeComponent every 4 seconds (TickIntervall is set to 1.0) and it works as it should.

It does not change the Address of the component.

I am going to do some more experiments with this but as long as you do not change the properties via the GameEditor during runtime it should work.

Yes, this is exactly what I was after. I’m pretty sure this is your issue. As a simple test, can you map the toggling of the boolean to a key press instead?

Generally speaking, changing properties of an actor via the properties panel during gameplay is going to result in odd behavior like this. I’m fairly confident that when you change a property during gameplay the editor will “refresh” the actor as you’ve now just change a property which could effect its construction.

Keybinding also works.

Generally speaking, changing properties of an actor via the properties panel during gameplay is going to result in odd behavior like this. I’m fairly confident that when you change a property during gameplay the editor will “refresh” the actor as you’ve now just change a property which could effect its construction.

Yes it realy looked like it was creating a new instances or alt least refreshing the instance and pointer.

Thank you very much. Now I know ho to handle this and can go on :slight_smile: Thanks a lot. Have a nice evening/day bro. :slight_smile:

That’s money, best of luck!!