Spawn random AActor

Hello!
I know there exist similar topics like this, but I didn’t find the right solution (e.g. how to fill the array) so let me ask specific.

I’m quite new to UE4, halfway through an udemy.com course and currently challenging myself to do one project without any course guidance. So I decided to try on a Tetris game.

So far it works quite smoothly. For the latest task I feel like I found a working, but yet messy / unintelligent solution, so I’m asking for feedback concerning best practice.

I have made a general ATetromino C++ class which is parent to ATetromino_BP class and ATetromino is based on APawn.
Each of the seven different tetrominos is a blueprint e.g. T-Shape_BP which is based on ATetromino_BP, so that the Key Input settings can be used when possessed, which are only defined in ATetromino_BP.

So now I want to spawn a random tetromino in the tetris game. My approach is like this:

  • C++: Define a variable for each Tetromino shape in the GameManager.h, which is based on a USceneComponent and attached to the GameModeBP


    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_1;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_2;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_3;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_4;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_5;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_6;

    UPROPERTY(EditDefaultsOnly, Category = Setup)
    TSubclassOf<ATetromino> Tetromino_7;


  • GameModeBP select the respective BPs for the 7 variables

Unbenannt.PNG

  • Spawn random Tetromino using Switch statement


void UTetrisGameManager::SpawnThisTetromino()
{
    int32 Tetromino_Type = FMath::RandRange(1, 7);
    UE_LOG(LogTemp, Warning, TEXT("This Tetromino will be Nr: %d"), Tetromino_Type);
    switch (Tetromino_Type)
    {
    case 1: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_1, StartPosition, FRotator(0, 0, 0)); break;
    case 2: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_2, StartPosition, FRotator(0, 0, 0)); break;
    case 3: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_3, StartPosition, FRotator(0, 0, 0)); break;
    case 4: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_4, StartPosition, FRotator(0, 0, 0)); break;
    case 5: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_5, StartPosition, FRotator(0, 0, 0)); break;
    case 6: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_6, StartPosition, FRotator(0, 0, 0)); break;
    case 7: ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetromino_7, StartPosition, FRotator(0, 0, 0)); break;
    }
}


So as I said it’s my clumsy code that works for now but even I realize, there must be a better way.
Like for example creating an Array of pointers to those Tetrominos but the way it is done now, the variables Tetromino_1 …7 are no pointers but actual Tetromino_BPs like T-Shape and therefore cannot be fitted into an array of ATetromino* pointers. That’s why my array approach has failed. Also the way I introduce the different Tetrominos in the Blueprint might not be optimal?

Thanks for help! It’s great fun creating something in UE4/C++. BR, Lutz

You can create an array of TSubclassOf to store references to all your Tetromino classes.



UPROPERTY(EditDefaultsOnly, Category = Setup)
TArray<TSubclassOf<ATetromino>> Tetrominos;


And then you can spawn a random Tetromino like this:



if (Tetrominos.Num() > 0)
{
    int32 RandomIndex = FMath::RandRange(0, Tetrominos.Num() - 1);

    ThisTetromino = GetWorld()->SpawnActor<ATetromino>(Tetrominos[RandomIndex], StartPosition, FRotator(0, 0, 0));
}


Ahh, thats so much better! Perfect solution - thanks a lot Ogniok!