Download

How to save property values set in OnConstruction?

Hello,

I’m currently investigating how I can setup a dungeon generation system for our game.

Not a completely procedural dungeon generation, but a serie of rooms created separately, and which would be used by the dungeon manager to populate the level.

What I would like, is to avoid to set up a lot of variables everywhere to know what the rooms look like.

So I first started with a level data class which holds an array of TSubClassOf< ARWCRoom >


UCLASS()
class RWC_API URWCLevelData : public UDataAsset
{
    GENERATED_BODY()

public:

    UPROPERTY( EditAnywhere )
    TArray< TSubclassOf< ARWCRoom > > RoomClassTable;
};

This data asset is given to the ARWCDungeon class, which in its BeginPlay selects the rooms randomly, and connects them:


void ARWCDungeon::BeginPlay()
{
    Super::BeginPlay();

    for ( auto room_class : LevelData->RoomClassTable )
    {
        if ( auto * room = Cast< ARWCRoom >( room_class->GetDefaultObject() ) )
        {
            const auto door_count = room->GetDoorCount();

            UE_LOG( LogRWC, Warning, TEXT( "Door count : %i" ), door_count );
        }
    }
}

To connect the rooms between them, I first need to know how many doors each room has, and the position and rotation of each door too.

I would like these informations to be content-driven. I would like to avoid to have to let the designer first create the room. then fill the relevant properties on the room blueprint.
As a matter of simplicity, I would prefer him to create the room, and let the room blueprint figure out how many doors it contains, and their transforms, so the dungeon blueprint can do its work>

I thought the OnConstruction would be the function to use to update those properties:


UCLASS()
class RWC_API ARWCRoom : public AActor
{
    GENERATED_BODY()

public:

    FORCEINLINE int GetDoorCount() const { return DoorCount; }

    virtual void OnConstruction( const FTransform & transform ) override;

private:

    UPROPERTY( EditAnywhere )
    int DoorCount;
};


void ARWCRoom::OnConstruction( const FTransform & transform )
{
    auto component_array = GetComponentsByClass( UChildActorComponent::StaticClass() );

    DoorCount = 0;

    for ( auto * actor_component : component_array )
    {
        if ( auto *  child_actor_component = Cast< UChildActorComponent > ( actor_component ) )
        {
            if ( auto * door = Cast< ARWCDoor >( child_actor_component->GetChildActor() ) )
            {
                DoorCount++;
            }
        }
    }
}

At this point, the OnConstruction function is called when I edit my room in the editor, and DoorCount has the correct value.

But when I access GetDoorCount() on the CDO of the room, its value remains 0.

Are there any other function I should use to save thoses values in the asset?

Is it possible to have it work the way I would like? Or am I stuck having to let the designers will every values on each blueprint, which is error-prone?

Thanks!

Why do you expect CDO to change default values when you edit an instance?

Btw… try that inside objects constructor; but inside:

if (GEngine) {
const auto &World = GetWorld();
if (World) {
// count doors…
}
}

My bad about CDO.

I don’t know why I thought it was saved per-instance and not per class…

So I guess I’ll have to let the designers sort the various rooms in seperate lists, depending on their door count

Thanks

Based on my painful experience with setting values in onconstruction, you need uproperty() or ufunction(). Not sure if that was the same case with your example.

I don’t know. Until I find out a better solution, I will stick with having to sort the rooms myself in separate arrays, depending on their number of doors…