Access the variables of a TSubclassOf

Hello

Im working on a semi-procedural BP Based level generator in a nutshell all my level “templates” are a blueprint made of various static mesh components, i have a ProceduralManager UObject class that is initialized once the game begins , then based on various inputs it spawns the Blueprint Templates / Rooms

My issue is that before i spawn the room Blueprint i need to access one of its properties to make a check, I have all the “Rooms” linked to a main blueprint as On a array as this
TArray > LinkedRooms;

But when i try to access any of its member the compiler shows me that the member isnt part of it… To be exact,
error C2039: ‘bIsSpawnRoom’ : is not a member of ‘UObject’

#pragma once

#include "Object.h"
#include "PCManager.generated.h"



USTRUCT()
struct FRoomTheme
{
	UPROPERTY(EditAnywhere,Category = ThemeInfo)
		TArray<TSubclassOf<class APCRoom> > LinkedRooms; // All the rooms / templates linked to this theme
};

/**
 * 
 */
UCLASS(Blueprintable)
class UPCManager : public UObject
{
	GENERATED_UCLASS_BODY()

	virtual void InitGeneration();

	UPROPERTY(EditAnywhere, Category = ProceduralGeneration)
	bool bPickRandomSpawnTheme;

	UPROPERTY(EditAnywhere, Category = ProceduralGeneration)
	FRoomTheme CurrentTheme; // Theme the generation will start with if bPickRandomThemeAtStart is false 
	
};

.CPP

#include "PCGame.h"
#include "PCManager.h"


UPCManager::UPCManager(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{

}

void UPCManager::InitGeneration()
{
	FVector SpawnLoc;
	FRotator TheRot;

	if (bPickRandomSpawnTheme)
	{

	}

	 // initiate the current theme from editor if we are not supposed to pick a random one
	for (int32 i = 0; i < CurrentTheme.LinkedRooms.Num(); i++) 
	{
		if (CurrentTheme.LinkedRooms.IsValidIndex(i)) // index is valid ? no crash and continue
		{
			if (CurrentTheme.LinkedRooms[i]->bIsSpawnRoom) // HERE! Is the Issue!!
			{
				()->SpawnActor(CurrentTheme.LinkedRooms[i]);
			}
		}
    }

}

Thanks

TSubclassOf is a special template of UClass which only accepts specific subclasses of some class… so it’s still UClass which is just a class specifier which you can spawn things from, but it does not have varables or functions of such class. But you can get default object which is master copy of object of your class which should contain default variable which you can use before spawning that object.

So try this insted:

CurrentTheme.LinkedRooms[i]->GetDefaultObject<APCRoom>()->bIsSpawnRoom
1 Like

Oh i see , that makes sense Thanks!

I encountered a second issue though…

I created a blueprint of my PCManager class which extends UObject, I can properly spawn and access it fine but my problem is that it only spawns the class, meaning it doesnt load the Blueprint containing all the information

Im loading and spawing the object using

// Gamemode .CPP

APCGameGameMode::APCGameGameMode(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	
	static ConstructorHelpers::FObjectFinder<UBlueprint>  PCManagerObject(TEXT("Blueprint'/Game/Blueprints/BP_ProceduralManager'"));
	//Blueprint'/Game/Blueprints/BP_ProceduralManager.BP_ProceduralManager'
	if (PCManagerObject.Object != NULL)
	{

		ProceduralGenManager = NewObject<UPCManager>(PCManagerObject.Object);
	}

}

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

	if(ProceduralGenManager)
	{
		ProceduralGenManager->InitGeneration();
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Procedural Generation init"));
   UE_LOG(LogTemp, Warning, TEXT("Current Theme Rooms are %d"), ProceduralGenManager->CurrentTheme.LinkedRooms.Num()); // Returns 0, The array is filled in the BP
		
	}
}

Im kind of confused, according to the docs NewObject takes an Object and a Class Since im providing the blueprint object for the class shouldnt it spawn it with the blueprint information as well? Or since im only giving the class its doing exactly that and just creating the object based on the class?

I think you need to spawn from UClass, with ConstructObject

https://docs.unrealengine.com/latest/INT/API/Runtime/CoreUObject/UObject/ConstructObject/1/index.html

You were right!, Using ConstructObject works perfect

Thanks a lot !