How to include (add) a Blueprint component to C++ Actor?

There is a Blueprint Component “FlatComponent” based on ActorComponent, it needs to be somehow added to the C++ Actor, which is called “FlatActor”.

How can I do it?

I tried adding this to FlatActor.h:

UPROPERTY(VisibleAnywhere)
TSubclassOf<class UActorComponent> FlatCompClass;

UPROPERTY()
UActorComponent* FlatComp;

And I don’t know what to do next.


What i want to see:

comps

1 Like

Try looking at the source code for ACharacter. The constructor will show you how to properly initialize a component.

ACharacter::ACharacter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		FName ID_Characters;
		FText NAME_Characters;
		FConstructorStatics()
			: ID_Characters(TEXT("Characters"))
			, NAME_Characters(NSLOCTEXT("SpriteCategory", "Characters", "Characters"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;

	// Character rotation only changes in Yaw, to prevent the capsule from changing orientation.
	// Ask the Controller for the full rotation if desired (ie for aiming).
	bUseControllerRotationPitch = false;
	bUseControllerRotationRoll = false;
	bUseControllerRotationYaw = true;

	CapsuleComponent = CreateDefaultSubobject<UCapsuleComponent>(ACharacter::CapsuleComponentName);
	CapsuleComponent->InitCapsuleSize(34.0f, 88.0f);
	CapsuleComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);

	CapsuleComponent->CanCharacterStepUpOn = ECB_No;
	CapsuleComponent->SetShouldUpdatePhysicsVolume(true);
	CapsuleComponent->SetCanEverAffectNavigation(false);
	CapsuleComponent->bDynamicObstacle = true;
	RootComponent = CapsuleComponent;

	bClientCheckEncroachmentOnNetUpdate = true;
	JumpKeyHoldTime = 0.0f;
	JumpMaxHoldTime = 0.0f;
    JumpMaxCount = 1;
    JumpCurrentCount = 0;
	JumpCurrentCountPreJump = 0;
    bWasJumping = false;

	AnimRootMotionTranslationScale = 1.0f;

#if WITH_EDITORONLY_DATA
	ArrowComponent = CreateEditorOnlyDefaultSubobject<UArrowComponent>(TEXT("Arrow"));
	if (ArrowComponent)
	{
		ArrowComponent->ArrowColor = FColor(150, 200, 255);
		ArrowComponent->bTreatAsASprite = true;
		ArrowComponent->SpriteInfo.Category = ConstructorStatics.ID_Characters;
		ArrowComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_Characters;
		ArrowComponent->SetupAttachment(CapsuleComponent);
		ArrowComponent->bIsScreenSizeScaled = true;
	}
#endif // WITH_EDITORONLY_DATA

	CharacterMovement = CreateDefaultSubobject<UCharacterMovementComponent>(ACharacter::CharacterMovementComponentName);
	if (CharacterMovement)
	{
		CharacterMovement->UpdatedComponent = CapsuleComponent;
		CrouchedEyeHeight = CharacterMovement->CrouchedHalfHeight * 0.80f;
	}

	Mesh = CreateOptionalDefaultSubobject<USkeletalMeshComponent>(ACharacter::MeshComponentName);
	if (Mesh)
	{
		Mesh->AlwaysLoadOnClient = true;
		Mesh->AlwaysLoadOnServer = true;
		Mesh->bOwnerNoSee = false;
		Mesh->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPose;
		Mesh->bCastDynamicShadow = true;
		Mesh->bAffectDynamicIndirectLighting = true;
		Mesh->PrimaryComponentTick.TickGroup = TG_PrePhysics;
		Mesh->SetupAttachment(CapsuleComponent);
		static FName MeshCollisionProfileName(TEXT("CharacterMesh"));
		Mesh->SetCollisionProfileName(MeshCollisionProfileName);
		Mesh->SetGenerateOverlapEvents(false);
		Mesh->SetCanEverAffectNavigation(false);
	}

	BaseRotationOffset = FQuat::Identity;
}
1 Like

static ConstructorHelpers::FClassFinder FlatCompClass(TEXT("/Game/YourAssetPath"));

Well I wrote this:

static ConstructorHelpers::FClassFinder<UActorComponent> FlatCompOb(TEXT("Blueprint'/Game/Components/FlatComponent.FlatComponent_C'"));
	FlatCompClass = FlatCompOb.Class;

	UClass* baseClass = FindObject<UClass>(ANY_PACKAGE, TEXT("ActorComponent"));
	if (FlatCompClass->IsChildOf(baseClass))
	{
		UActorComponent* NewComp = NewObject<UActorComponent>(FlatCompClass);

		NewComp->RegisterComponent();
		
	}

The path is defined, but my FlatComponent is not added as a component.

Try using CreateDefaultSubobject instead.

I tried but it didn’t work, can you explain how to make it work?

image

There is also one defined by the UObject class.

FlatComp = Cast<UActorComponent>(CreateDefaultSubobject(TEXT("Component Display Name"), FlatCompOb.Class, FlatCompOb.Class, false, false));

// Latter two booleans you should check what they do, funnily enough the C++ API docs on the ConstructorHelper's side makes it more clear while the UObject one is not commented.

Thanks, it works!
But there is a problem: in order to use my FlatComponent in Blueprints, I need to use Cast To FlatComponent to edit it.

image

And is it possible to get variables from my Component in C++?
If so, how?

Well… it’s inheritance 101 - your “flat component” is both an UActorComponent and UFlatComponent. But in your header, you’ve defined the pointer as UActorComponent*.

So instead of declaring FlatComp as UActorComponent*, declare it as UFlatComponent*. At this point you might want to check on forward declaring so you don’t need to add any includes in the header file, but rather can add them to the .cpp file.