Ue5 in C++, How to Create a Component Based on Two (Or More) Components?
I First Have to Say That I'm New to Unreal: / What I Would Like Is Two Classes: One Would Be a Component (Cubeblockcomponent) Which Would Be a Collisionbox...
I first have to say that I'm new to Unreal :/
What I would like is two classes : One would be a component (CubeBlockComponent) which would be a CollisionBox with a Mesh, so I would like to use a UBoxComponent and a UStaticMeshComponent. Second would be an Actor (ModuleActor) combining several CubeBlockComponent.
I was able to get the desired behavior with an actor composed of several BoxComponent and StaticMeshComponent, but configurating them the same way each time I want to add one block is a pain, thus the need of a CubeBlockComponent.
My problem is I can't figure out how to do it properly. What should I do ?
I tried creating a c++ class (CubeBlockComponent) inherited from USceneComponent. I added a UStaticMeshComponent and a UBoxComponent :
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent* cubeStaticMesh;
UPROPERTY(EditAnywhere)
UBoxComponent* boxCollision;
And created them with CreateDefaultSubobject in the constructor:
// Create box collision
boxCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollision"));
boxCollision->SetBoxExtent(FVector(40.f, 40.f, 40.f));
boxCollision->SetupAttachment(this);
// Create Cube static mesh
cubeStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CubeStaticMesh"));
cubeStaticMesh->SetupAttachment(boxCollision);
Then, back in UE5 editor, I can make a blueprint component (BpCubeBlockComponent) based on my class (CubeBlockComponent). But this is bad as in BpCubeBlockComponent I can only modify cubeStaticMesh and boxCollision via "Open selecttion in Propery Matrix". And also, when I combine several BpCubeBlockComponent in an actor, the meshes just stays at the origin.
I feel like I should just create a class inheriting UBoxComponent, and basically recreating all UStaticMeshComponent functionalities inside the class, which would be a pain...
1 Answer
After hours of testing I found a solutions which I found quite good.
First, one should know that adding a component from another component is not recommended ; I guess it does not go well with Actor/component principle.
That said I was able to do it by overloading the OnRegister() method. So once a component is registered, it can attach other component to itself.
This is how it looks :
// CubeBlockComponent.h
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent), Blueprintable )
class BASIC2D_API UCubeBlockComponent : public UBoxComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UCubeBlockComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
// Needed to attach other component
virtual void OnRegister() override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent* cubeStaticMesh;
};
And
CubeBlockComponent.cpp
#include "CubeBlockComponent.h"
// Sets default values for this component's properties
UCubeBlockComponent::UCubeBlockComponent()
{
// 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.
PrimaryComponentTick.bCanEverTick = true;
// Create Cube static mesh, wait OnRegister to attach
cubeStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CubeStaticMesh"));
}
// Called when the game starts
void UCubeBlockComponent::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void UCubeBlockComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
void UCubeBlockComponent::OnRegister()
{
Super::OnRegister();
cubeStaticMesh->SetupAttachment(this);
}