Solved!
I used a method where I would store three TArrays in the base class, with each of them representing the subclass, physics constraint component, and the constraint names. The following code is placed in the base class’ header file. I use APawn because, frankly, everything is in APawn.
UCLASS()
class TUTORIAL_API ABaseClass : public APawn
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CustomProperties) TArray<ASubClass*> SubClassArray;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CustomProperties) TArray<UPhysicsConstraintComponent*> PhysicsConstraintArray;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CustomProperties) TArray<FName> ConstraintNameArray;
...
...
}
Then to initialize the arrays, first you need to create the following components for the PhysicsConstraintArray and the ConstraintNameArray.
ABaseClass::ABaseClass(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
for (int32 i = 0; i < 4; i++){
//Names
FString Name = "Frame_" + FString::FromInt(i);
this->ConstraintNameArray.Push(FName(*Name));
//Physics Constraints
UPhysicsConstraintComponent* PhysicsConstraint = ObjectInitializer.CreateDefaultSubobject<UPhysicsConstraintComponent>(this, this->ConstraintNameArray*);
PhysicsConstraint->SetWorldLocation(this->GetActorLocation());
this->PhysicsConstraintArray.Push(PhysicsConstraint);
}
...
...
}
Then in the OnConstruction(Transform) override function, you would then start initializing the subclass array. Note that the ConstraintNameArray.Num() is then used as an array size counter, so you don’t have to define constants here and there.
void ABaseClass::OnConstruction(const FTransform& Transform){
Super::OnConstruction(Transform);
//First loop needs initial values passed in, so successive calls can then be swapped for last initialized actors.
FVector Height(0.0f, 0.0f, 100.0f); //How high from the initial world origin. Since the default floor mesh in a blank level is 80 UE4 units high, I set it to 100.
FActorSpawnParameters Params;
Params.Owner = this; //Setting the owner as the base class. When spawning actors, actors will have the owner as their parents.
USceneComponent* Scene = this->GetRootComponent();
UPrimitiveComponent* Primitive = this->BoxCollider;
//Initializing Subclass array.
for (int32 i = 0; i < ConstraintNameArray.Num(); i++){
ASubClass* Class = this->GetWorld()->SpawnActor<ASubClass>(ASubClass::StaticClass(), Height, this->GetActorRotation(), Params);
Class->BoxCollider->AttachTo(Params.Owner->GetRootComponent());
//Set whatever constraining limits you need here
UPhysicsConstraintComponent* Physics = this->PhysicsConstraintArray*;
Physics->AttachTo(Scene, NAME_None, EAttachLocation::KeepWorldPosition);
Physics->SetConstrainedComponents(Primitive, NAME_None, Class->BoxCollider, NAME_None);
Physics->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Locked, 0.0f);
Physics->SetAngularSwing2Limit(EAngularConstraintMotion::ACM_Locked, 0.0f);
Physics->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Locked, 0.0f);
//Prepare for next iteration.
Params = {};
Params.Owner = Class;
Scene = Class->GetRootComponent();
Primitive = Class->BoxCollider;
}
...
...
}
That is all.