How to handle child components

Hello. I am completely new to Unreal Engine 5, but I have some experience with C++. I was trying stuff out with Unreal, and I wanted to make a Planet with a Moon that revolves around it while the Planet and the Moon itself are rotating. I am trying to fiddle with Child Components (I am guessing that this is how they are called?) I cannot understand how to access “Moon” in my hierarchy. At the moment I am rotating the entire actor, therefore everything in my hierarchy is rotating, but how can I rotate just Planet? Or just Moon?
image

Ok so you want to attach the moon to the planet which makes sense, but you want the planet to have its own rotation rate and the moon to have its own rotation rate. There’s a catch : if the planet rotates, its child components are gonna rotate with it, and in this specific case you don’t want that.

This can be avoided using a SpringArm component. Those are primarily designed to handle third-person camera behind a character, so that the camera follows the character but when character rotates it doesn’t rotate the camera with it (so mouse keeps full control of camera). However SpringArms are not limited to camera management and can be used for our purpose here. The SpringArm let us attach moon to the planet at a specific distance (arm length), and it has that special feature which allows us to NOT inherit its parent rotation.

I also attached the planet to the center via a spring arm, because both are going to work in a very similar way. Also added arrows for visualization.


When you have components, they are automatically assigned to variables which you can use in blueprint. Simply drag and drop them (or right click and type their name) to use them. For now I’m just gonna make them rotate around themselves, at different rates, independently (thanks to the spring arm) :

Drag and drop either from the hierarchy, or from variables, both work.

aaaaaa


Now we can make the moon rotate around the planet. The SpringArm has its pivot on the planet and the moon is attached at the other end. All we have to do is rotate the SpringArm around itself.
While we are at it, do the same for the planet :

aaaaaa

3 Likes

Thank you for your perfect explanation! I didn’t know you could use spring arms like that. I also wanted to ask you another thing: In your explanation you say

When you have components, they are automatically assigned to variables which you can use in blueprint.

How would this work in C++? If I create an actor component with C++ and I then add Planet and Moon, does that mean that I automatically get two actor variables called “Planet” and “Moon”?

Not in C++ obviously.

You can either create the entire hierarchy in C++, putting them in C++ variables, like so :

UCLASS()
class ASomeActor : public AActor
{
	GENERATED_BODY()

	ASomeActor();

	UPROPERTY(EditAnywhere)
	USphereComponent* Planet;

	UPROPERTY(EditAnywhere)
	USphereComponent* Moon;
};
ASomeActor::ASomeActor()
{
	RootComponent = CreateDefaultSubobject<USceneComponent>("Root");

	Planet = CreateDefaultSubobject<USphereComponent>("Planet");
	Planet->SetupAttachment(RootComponent);
	Planet->SetRelativeLocation(FVector(300.f, 0, 0));

	Moon = CreateDefaultSubobject<USphereComponent>("Moon");
	Moon->SetupAttachment(Planet);
	Moon->SetRelativeLocation(FVector(100.f, 0, 0));
	Moon->SetRelativeScale3D(FVector(0.2f));
}

Then when you make a child BP class, the component tree is inherited from its parents.

They don’t seem to appear in the “variables” section, but you can still drag and drop directly from components hierarchy.

It is a bit less flexible as inherited component cannot be swapped around. The inherited hierarchy is fixed. At least in the blueprint designer. At runtime you can still reattach components around using runtime attachment functions.

Hierarchy aside, the EditAnywhere tag still lets us modify components internal values in BP (right side panel).


Alternatively, you can declare C++ variables and leave them empty, to be filled in by BP child classes.

UCLASS()
class ASomeActor : public AActor
{
	GENERATED_BODY()

	ASomeActor();

public:

	UPROPERTY(BlueprintReadWrite)
	USphereComponent* Planet;

	UPROPERTY(BlueprintReadWrite)
	USphereComponent* Moon;
};
ASomeActor::ASomeActor()
{
    // No hierarchy

    PrimaryActorTick.bCanEverTick = true;
}

Those variables will of course be null in c++ constructor so you cannot do anything there, but you can totally use them at runtime (BeginPlay, Tick, etc.) provided you check for their validity.

//.h
virtual void Tick(float dt) override;

//.cpp
void ASomeActor::Tick(float dt)
{
	if (Moon)
	{
		Moon->AddLocalRotation(dt * FRotator(0, 90.f, 0));
	}
}

Then add components in the BP child class (the DefaultSceneRoot is created automatically when there is no root defined in C++)

Then assign them to the C++ variables in constructor.
Note that the C++ variables do not appear anywhere because the UI doesn’t show inherited variables. But if you right click and type variable names you can access them (thanks to BlueprintReadWrite tag).

image

1 Like

Thanks again for the answer! This was really helpful, and it helped me understand how to use inheritance in Unreal. Cheers.