Unable to Spawn blueprint subclass in constructor

So I am trying to create a large paddle object that the player will fly around in this game. The paddle is made up up buildingblocks, which are components on the paddle. The building blocks are children of the UStaticMeshComponent.

I have in the .h

UPROPERTY(BlueprintReadWrite, EditAnywhere)
TSubclassOf<class UPaddleBlockBase> BuildingBlockClass;

This lets me select the building block class in the editor. Great.

In the Constructor, after I’ve set up the camera and a Few other things, I do this block of Code to generate some blocks. that form the Paddle.

FVector Loc;
for (int32 i = 0; i < PaddleHeight; i++)
{
	for (int32 j = 0; j < PaddleWidth; j++) {
		FName name = *FString::Printf(TEXT("Block %i, %i"), i, j);
		UPaddleBlockBase* NewBlock = CreateDefaultSubobject<UPaddleBlockBase>(name);

		Loc.Y = -(BlockWidth * PaddleWidth) + (j * BlockWidth * 2) + BlockWidth;
		Loc.Z = BlockHeight * PaddleHeight - (i * BlockHeight * 2) - BlockHeight;
		NewBlock->SetWorldLocation(Loc);
		NewBlock->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
		NewBlock->CollisionBox->SetWorldLocation(Loc);
		NewBlock->CollisionBox->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
		PaddleBlocks.Add(NewBlock);

	}
}

This gives me a nice wall, but its made up of the c++ version of the blocks, not the blueprint version. I’d love to be able to start crapping out blueprint children with different block types selected, but I can’t for the life of me figure out how to get it to spawn the blueprint version in the constructor. I’ve looked at options to have it only spawn the blocks after beginplay, but I have run into issues there too. I just want to spawn all the blocks out of my blueprint subclass.

You can just try to replace this

UPaddleBlockBase* NewBlock = CreateDefaultSubobject(name);

with this

UObject* NewBlock = CreateDefaultSubobject(name, BuildingBlockClass, BuildingBlockClass, true, false));

Then Cast it and use…

FVector Loc;
for (int32 i = 0; i < PaddleHeight; i++)
{
for (int32 j = 0; j < PaddleWidth; j++) {
FName name = *FString::Printf(TEXT(“Block %i, %i”), i, j);

			UObject* NewBlock = CreateDefaultSubobject(name, BuildingBlockClass, BuildingBlockClass, true, false);
			NewBlock = Cast<UPaddleBlockBase>(NewBlock);
			
			Loc.Y = -(BlockWidth * PaddleWidth) + (j * BlockWidth * 2) + BlockWidth;
			Loc.Z = BlockHeight * PaddleHeight - (i * BlockHeight * 2) - BlockHeight;
			if (NewBlock) {

				NewBlock->SetWorldLocation(Loc);
				NewBlock->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
				NewBlock->CollisionBox->SetWorldLocation(Loc);
				NewBlock->CollisionBox->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
				PaddleBlocks.Add(NewBlock);
			}

		}

So I’ve updated my code to be like this. Honestly, its the weekend and my brain is a little fried. This doesn’t compile though. I have a feeling I’m doing something simple but stupid wrong with the casting.

All the errors in the errorlog are to do with it not knowing NewBlock is a UPaddleBlockBase. Still thinks its a Uobject.

Everything shoud work normally, here is some sample code SubObj.7z — Yandex.Disk

Yea, I’m not sure why the cast isn’t working. I read somewhere on I think a 2015 post that you can’t cast inside the constructor… but it doesn’t seem correct to me, although the experimentation I’ve done would indicate that is somehow true. Either way I’ve figured out another way to accomplish my task using the game instance to store every possible block subtype BP in an array, then when I spawn the paddle I just get it from the game instance blueprint. What is infuriatingly confusing however, is that I do a successful casting in this to the BP version of the game instance, but for whatever reason it just does not let me cast the NewBlock to a BP version of UPaddleBlockBase.

	static ConstructorHelpers::FObjectFinder<UClass>DataObjectAsset(TEXT("Class'/Game/BP_HyperPongGameInstance.BP_HyperPongGameInstance_C'"));
	if (DataObjectAsset.Succeeded())
	{
		TheData = Cast<UPuzzlePlatformsGameInstance>(DataObjectAsset.Object->GetDefaultObject());
		BuildingBlockClass = TheData->BlockTypes[BlockTypeIndex];
		if (BuildingBlockClass) {

			FVector Loc;
			for (int32 i = 0; i < PaddleHeight; i++)
			{
				for (int32 j = 0; j < PaddleWidth; j++) {
					FName name = *FString::Printf(TEXT("Block %i, %i"), i, j);


					UPaddleBlockBase* NewBlock = (UPaddleBlockBase*) CreateDefaultSubobject(name, UPaddleBlockBase::StaticClass(), BuildingBlockClass, false, false, false);

... More stuff down here happens, unimportant.

So weird quirks going on with this is that I can’t extend the base paddle class with BP and have it get the BlockTypeIndex from the BP through the UProperty on BlocktypeIndex, so it always considers it to be 0. Kinda okay with each different paddle having its own construction maths though. Some can be vertical this way, or other odd shapes. I appreciate your help on this. Even though its not quite what I initially imagined I think this will end up better.

I just check it on my 4.23 and it is working:

if (BuildingBlockClass) { // check that we have block class selected
	for (size_t i = 0; i < 10; i++) {
		for (size_t j = 0; j < 10; j++) {
			
			UObject* NewBlock = CreateDefaultSubobject(FName(*(FString::Printf(TEXT("Name_%d_%d"), i, j))), BuildingBlockClass, BuildingBlockClass, true, false);
			auto casted = Cast<UPaddleBlockBase>(NewBlock);
			casted->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
		}
	}
}

The several points are - different names for each and that natively added components ar not visible in editor property panel

I know its been a bit but thanks, this stuff helped a great deal. How do I mark yours as my correct answer?

Kehel18 and I worked through this in the comment chain.