Having components inside of a component

Good afternoon,

I’m trying to build an “InteractionSystem”.

Basically, I want to have a c++ ActorComponent with a UTextRender that I can turn visible or not if the actor can be interacted with,

My problem:

  • I can’t attach to the root component of the actor I’m attaching this component to.
  • I can’t seem to be able to use ToggleVisibility on the text. I tried to debug and made sure it was reaching the point with a print log.

In the .h

    UPROPERTY(EditAnywhere, BlueprintReadWrite, transient, Category = "Default")
	 UTextRenderComponent * interactText;

In the .cpp and If I don’t check that all of this exist, the editor crashes.
In the constructor:

	if (GetOwner()){
		if (GetOwner()->GetRootComponent()){
			UE_LOG(LogTemp, Log, TEXT("RootComponent exist"));
			interactText->AttachParent = GetOwner()->GetRootComponent();
		}
	}

The set-up of the interact text class.

/*
Method setting the default data for the interaction system interact text.
*/
void UInteractionSystem::setInteractText(){
	// Create the object and make it visible
	interactText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("InteractText"));
	interactText->SetHiddenInGame(true);

	interactText->SetText(LOCTEXT("InteractText", "Interact"));

	// Default to black color
	interactText->SetTextRenderColor(FColor(0, 0, 0, 255));

	// Font size
	interactText->SetWorldSize(72);

	// Align to center
	interactText->VerticalAlignment = EVerticalTextAligment::EVRTA_TextCenter;

	// Put the text over the actor head.
	interactText->AddLocalOffset(FVector(0, 0, 150));

	interactText->RegisterComponent();
}

Thank you.

Hey wiwip-

When is setInteractText() being called? It appears that you are doing interactText->AttachParent prior to the CreateDefaultSubobject<> call. This would cause a crash since interactText is NULL when AttachParent is set. Moving interactText = CreateDefaultSubobject(TEXT("InteractText")); to the constructor above the other code you posted should help.

Cheers

No, it’s called just before the attach

	bWantsBeginPlay = true;
	PrimaryComponentTick.bCanEverTick = false;

	setInteractText();

	if (GetOwner()){
		if (GetOwner()->GetRootComponent()){
			UE_LOG(LogTemp, Log, TEXT("RootComponent exist"));
			
			interactText->AttachParent = GetOwner()->GetRootComponent();
		}
	}

Can you try putting your code inside a SceneComponent class rather than an ActorComponent class? SceneComponent inherits from ActorComponent and also has a transform to represent where it is in the level. Also, can you describe exactly how it isn’t working for you? Are you getting compile errors or is the text just not showing up in the editor or is it something else?

Thanks for the answer.

I will try the scene component.

The problem isn’t a crash or compile error.
It’s simply that the deffered attach using the stuff->attachParent isn’t working inside the editor or ingame except if I attach the components dynamically at the BeginPlay().

I corrected my problem. The deffered attach is only done on the actual component and not on his child so this corrected the situation.

	if (GetOwner()){
		if (GetOwner()->GetRootComponent()){
			UE_LOG(LogTemp, Log, TEXT("RootComponent exist"));
			
			interactSphere->AttachTo(this);
			interactText->AttachTo(this);
			cursorDetectSphere->AttachTo(this);

			this->AttachTo(GetOwner()->GetRootComponent());
		}
	}

Actually, this did the trick better. My previous answer could still crash the engine.

UInteractionSystem::UInteractionSystem()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	bWantsBeginPlay = true;
	PrimaryComponentTick.bCanEverTick = false;

	setInteractText();

	// Set delegates for range
	interactSphere->OnComponentBeginOverlap.AddDynamic(this, &UInteractionSystem::playerEnterRange);
	interactSphere->OnComponentEndOverlap.AddDynamic(this, &UInteractionSystem::playerExitRange);

	if (GetOwner()){
		// Depending on if a Root Component exist, assign or attach the component to Root Component
		if (!GetOwner()->GetRootComponent()){
			GetOwner()->SetRootComponent(this);
		} else {
			this->AttachParent = GetOwner()->GetRootComponent();
		}
		interactText->AttachTo(this);
	}

Is this answer holding valid? I am having conflicting results on my search for the answer to this enigma.
My Question About Roughly The Same Thing