Download

In a brand new project containing 1 blank level, how do I spawn 1 actor without possessing a pawn?

I understand that to spawn an actor, you would use this code:



FActorSpawnParameters Spawn;
Spawn.Owner = this;
this->GetWorld()->SpawnActor<ATest>(ATest::StaticClass(), FVector(FMath::FRand() * 5000.0f, FMath::FRand() * 5000.0f, FMath::FRand() * 5000.0f), FRotator(FMath::FRandRange(-180.0f, 180.0f), FMath::FRandRange(-180.0f, 180.0f), FMath::FRandRange(-180.0f, 180.0f)), Spawn);
this->Spawned = true;


Inside any function that is not in the constructor, which is ATest().

But, has anyone ever found out that you can’t spawn anything, or rather, you can’t even have any 1 actor spawning without the player possessing a pawn actor?

Is there a way to spawn an actor without forcing the player to possess a pawn?

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.