3

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...

bobombe
  • 51
  • 3

1 Answers1

2

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);
}
bobombe
  • 51
  • 3