Children of my custom USceneComponent do not use parents transform

I am having trouble setting up a custom USceneComponent and attaching it to my Pawn. I am trying to create the following hierarchy of components in my Pawns blueprint:

BP_BirdseyePawn - Inherits from ABirdseyePawn : public APawn:
-SceneComponent (RootComponent)
– UCameraMovementComponent (Custom USceneComponent)
—UStaticMeshComponent

I am having an issue where the UStaticMeshComponent does not follow the transform of the UCameraMovementComponent. When I move the UCameraMovementComponent the UStaticMeshComponent does not move at all.

The UStaticMeshComponent looks correctly attached to the UCameraMovementComponent in the blueprint editor:

However, during runtime I can see in the outliner that the mesh component is not a child of the UCameraMovementComponent:

If I drag a new static mesh component into the blueprint editor manually (i.e not inherited from c++) then the transforms are respected as I expect:

And in the outliner I see that this is also the case:

My classes are setup as follows:

ABirdseyePawn:

UCLASS()
class TOWERTYCOON_API ABirdseyePawn : public APawn
{
	GENERATED_BODY()

public:

	ABirdseyePawn();

public:	

	virtual void Tick(float DeltaTime) override;

	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	virtual void BeginPlay() override;

protected:

	UPROPERTY(EditDefaultsOnly)
	USceneComponent* view_target_;

	UPROPERTY(EditDefaultsOnly)
	UCameraMovementComponent* cam_movement_component_;
};

ABirdseyePawn::ABirdseyePawn()
{
	PrimaryActorTick.bCanEverTick = true;	

	//Root Component
	view_target_ = CreateDefaultSubobject<USceneComponent>(FName("PawnRoot"));
	view_target_->bAutoActivate = true;
	view_target_->bAutoRegister = true;
	this->SetRootComponent(view_target_);

	//Camera Movement Component
	cam_movement_component_ = CreateDefaultSubobject<UCameraMovementComponent>(FName("CameraMovement"));
	cam_movement_component_->bAutoActivate = true;
	cam_movement_component_->bAutoRegister = true;
	cam_movement_component_->SetupAttachment(RootComponent);
}


void ABirdseyePawn::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void ABirdseyePawn::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void ABirdseyePawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
}

ACameraMovementComponent:

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class TOWERTYCOON_API UCameraMovementComponent : public USceneComponent
{
	GENERATED_BODY()

public:	
	UCameraMovementComponent();

protected:
	virtual void BeginPlay() override;	

	UPROPERTY(EditDefaultsOnly, Category = Camera)
	UStaticMeshComponent* mesh_;


public:	
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
		
};

UCameraMovementComponent::UCameraMovementComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
	PrimaryComponentTick.SetTickFunctionEnable(true);

	mesh_ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	mesh_->bAutoActivate = true;
	mesh_->bAutoRegister = true;
	mesh_->SetupAttachment(this);
}

void UCameraMovementComponent::BeginPlay()
{
	Super::BeginPlay();
}

void UCameraMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

Can anybody help me understand what is going on here?

I have found the answer to my problem in this post:

My understanding of the problem is as follows:

In the constructor of my UCameraMovementComponent I set attachement to this:

UCameraMovementComponent::UCameraMovementComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
	PrimaryComponentTick.SetTickFunctionEnable(true);

	mesh_ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	mesh_->bAutoActivate = true;
	mesh_->bAutoRegister = true;
	mesh_->SetupAttachment(this);
}

When the CDO of my class is constructed, this is pointing to the CDO and not the specific instance of my class. Since mesh_ is a UPROPERTY it will be get replaced in the actual instance after construction with the version from the CDO. This means my class instance has a mesh_ that is attached to the CDO, and not my instance.

To Solve this issue I need to reattach the mesh_ to the correct parent when the component is registered (after the CDO values are copied)

void UCameraMovementComponent::OnRegister() {
    Super::OnRegister();
    this->mesh_->AttachToComponent(this, FAttachmentTransformRules::KeepRelativeTransform);
}

With this addition the component works as expected.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.