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!