This seems like it should be a common thing to need to do, but it’s causing me an unreasonable amount of grief.
In general, in my project, I’ve been building abstract C++ base classes which are then inherited by blueprint classes which are actually used in the game. I’d like to be able to have actors and components “self-assemble” by having them create the standard components I know they need in their constructors.
The problem, of course, is that since the blueprint classes don’t yet exist at compile time, I can’t reference their class type directly in code. Also, I’d prefer to avoid writing explicit path references into the code, since then if I move anything, everything breaks.
My plan was, in the C++ base class, to have a TSubclassOf variable which can be used by the blueprint child-class to specify which blueprint class the C++ parent class should spawn. For example, my player pawn needs to spawn some hand controllers, which are components. So the player pawn C++ base class has:
UPROPERTY(EditDefaultsOnly, Category = ComponentClasses)
TSubclassOf<UHandControllerComponent_Base> HandControllerComponentClass;
UPROPERTY(BlueprintReadOnly, Category = Components)
UHandControllerComponent_Base* Hand_Left;
To specify the class of hand controllers it will spawn (which are blueprint classes which inherit from the UHandControllerComponent native base class.)
HandControllerComponent is then set to be a reference to the blueprint hand controller class in the class defaults in the editor.
In the Pawn’s constructor, I build the new HandControllerComponents using CreateDefaultSubObject and the class type provided by HandControllerComponentClass:
if (IsValid(HandControllerComponentClass))
{
UE_LOG(VRArenaGeneral, Log, TEXT("Generating hand components"));
Hand_Left = (UHandControllerComponent_Base*)CreateDefaultSubobject(TEXT("Hand_Left"), UHandControllerComponent_Base::StaticClass(), HandControllerComponentClass->StaticClass(), false, false, false);
Hand_Left->SetupAttachment(RootComponent);
if (!IsValid(Hand_Left))
{
UE_LOG(VRArenaGeneral, Error, TEXT("Hand component creation failed"));
}
}
else
{
UE_LOG(VRArenaGeneral, Error, TEXT("No HandControllerComponent class specified for Pawn."));
}
However, the code always dumps out to the “No HandControllerComponent class specified for Pawn” error. I’ve verified that the HandControllerComponentClass are set in the defaults of the pawn I’m spawning.
This suggests to me that for some reason, values set in the default class properties aren’t yet available when the constructor runs, which means I’m screwed since I have no way to hardcode that class reference. I could do this later, but my understanding is that that has some serious negative effects on being able to work with the blueprint classes in the editor.
What is the correct way to do this? (Construct an actor out of blueprint classes in C++)