Spawning a Pawn

Hi everyone

I am trying to write a class that will spawn a pawn and i failed.

I have a pawn blueprint, i want to choose that from editor without adding to level and make spawn volume spawn that pawn.

Well, this class spawns nothing. There is a problem with it.

Here is the header file of SpawnVolume

#pragma once

#include "GameFramework/Actor.h"
#include "PursuerPawn.h"
#include "SpawnVolume.generated.h"

UCLASS()
class SHOOTBOMBERS_API ASpawnVolume : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ASpawnVolume();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	// Box component that defines spawn area
	UPROPERTY(EditAnywhere, Category = Spawn)
	UBoxComponent* SpawnVolume;

	// Pawn to be spawned
	UPROPERTY(EditAnywhere, Category = Spawn)
	// Maybe i shouldnt choose UClass, but AActor doesnt give me what i want
	class UClass* SpawnActor;

	// Minimum time required to spawn, Needed for random spawn time
	UPROPERTY(EditAnywhere, Category = Spawn)
	float SpawnTimeRangeMin;

	// Maximum time required to spawn, Needed for random spawn time
	UPROPERTY(EditAnywhere, Category = Spawn)
	float SpawnTimeRangeMax;

private:
	// Gives random spawn location
	FVector GetSpawnLocation() const;

	// Gives random spawn rotation
	FRotator GetSpawnRotation() const;

	// To keep lines shorter, returns origin of box component
	const FVector& GetBoxOrigin() const;

	// To keep lines shorter, returns extent of box component
	const FVector& GetBoxExtent() const;

	// Returns random spawn time between min and max
	float RandSpawnTime() const;
	
	// Time passed since last spawn
	float SpawnTimePassed;

	// Random spawn time decided
	float SpawnTimeRandom;

};

and source file

#include "ShootBombers.h"
#include "SpawnVolume.h"
#include "Kismet/GameplayStatics.h"
#include "PursuerPawn.h"


// Sets default values
ASpawnVolume::ASpawnVolume()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// A dummy root component
	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
	
	// Box component that defines spawn area
	SpawnVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolume"));
	// Dont ask, name says it
	SpawnVolume->AttachTo(RootComponent);

}

// Called when the game starts or when spawned
void ASpawnVolume::BeginPlay()
{
	Super::BeginPlay();

	// Set default values
	SpawnTimeRangeMin = 0.5f;
	SpawnTimeRangeMax = 1.5f;
	SpawnTimePassed = 0.f;
	SpawnTimeRandom = RandSpawnTime();

}

// Called every frame
void ASpawnVolume::Tick( float DeltaTime )
{
	// If you dont know what this line does, well...
	Super::Tick( DeltaTime );

	// If we have a SpawnActor and World
	if (SpawnActor || ())
	{
		// Add delta time to passed time
		SpawnTimePassed += DeltaTime;

		// If enough time passed, spawn object
		if (SpawnTimePassed >= SpawnTimeRandom)
		{
			// Substract random spawn time from passed time
			SpawnTimePassed -= SpawnTimeRandom;
			SpawnTimeRandom = RandSpawnTime();
			
			FActorSpawnParameters SpawnParameter;
			SpawnParameter.Owner = this;
			SpawnParameter.Instigator = Instigator;

			// Spawn the actor with random location and rotation
			AActor* const SpawnedActor = ()->SpawnActor<AActor>(SpawnActor->StaticClass(), GetSpawnLocation(), GetSpawnRotation(), SpawnParameter);
		}
	}
}

FVector ASpawnVolume::GetSpawnLocation() const
{
	// Gets a random location inside Box component
	FVector RandomPoint;

	RandomPoint.X = FMath::FRandRange(GetBoxOrigin().X - GetBoxExtent().X / 2.f, GetBoxOrigin().X + GetBoxExtent().X / 2.f);
	RandomPoint.Y = FMath::FRandRange(GetBoxOrigin().Y - GetBoxExtent().Y / 2.f, GetBoxOrigin().Y + GetBoxExtent().Y / 2.f);
	RandomPoint.Z = FMath::FRandRange(GetBoxOrigin().Z - GetBoxExtent().Z / 2.f, GetBoxOrigin().Z + GetBoxExtent().Z / 2.f);

	return RandomPoint;
}

FRotator ASpawnVolume::GetSpawnRotation() const
{
	// Gets a random rotation
	FRotator RandomRotation;

	RandomRotation.Pitch = FMath::FRand();
	RandomRotation.Yaw = FMath::FRand();
	RandomRotation.Roll = 0.f;

	return RandomRotation;
}

const FVector& ASpawnVolume::GetBoxOrigin() const
{
	// To keep lines short, returns origin of box component
	return SpawnVolume->Bounds.Origin;
}

const FVector& ASpawnVolume::GetBoxExtent() const
{
	// To keep lines short, returns extent of box component
	return SpawnVolume->Bounds.BoxExtent;
}

float ASpawnVolume::RandSpawnTime() const
{
	// Returns a random spawn time between Min and Max
	return FMath::FRandRange(SpawnTimeRangeMin, SpawnTimeRangeMax);
}

Question for you, why can’t you use AActor* for SpawnActor. The current spawning you have setup via ()->SpawnActor won’t support anything but actors. There are other functions to spawn things such as UObject.

When i use AActor, it ask for an actor inside level. How can i get an actor not added level, exist in Content folder?

Maybe i am asking for something silly. But i used to use Unity and i migrated 2 weeks before UE4 became free. But that was how i did things inside Unity. So i may be trying to do something silly.

You probably want:

UBlueprintGeneratedClass *factory; 

This is the type that can take a ‘blueprint’ object; you don’t need to use UObject *.

I can’t see anything obvious wrong with this…

Obviously be aware that even if you spawn a Pawn, the player will not control it; you must call Possess() on a PlayerController() to bind the Pawn to the PlayerController.

…but other than that. It seems more or less ok.

AActor* const SpawnedActor = ()->SpawnActor(factory, GetSpawnLocation(), GetSpawnRotation(), SpawnParameter);

Should definitely spawn an actor.

What happens when you run it? Does a new actor show up in the editor?

Try adding some debug messages (eg: UKismetSystemLibrary::PrintString(this, "Hit Value", true, true, FLinearColor(0.0,0.0,0.0));) to check that SpawnActor is actually being called…

If it is, what is the return? Is SpawnedActor NULL? Or has it got a value?

Ohh, thanks. Will try it out right away

There 2 ways to get UClass from class, from static function which does not require instace, every UOBject has it and you can replace AMyPawn with any other UOBject class (But SpawnActor works only with AActors)

AMyPawn::StaticClass()

Or from instance of existing object

ActorPointerVarable->GetClass()

Actually, i am having a hard time implementing it. Cant use UBlueprintGeneratedClass with SpawnActor.

How can i use it with SpawnActor?

By the way, this is for spawning purposes. Will work on AI later. It is training.

Yes you are right. But what i want is not to use an actor from level. I want it to be loaded from Content folder. And if i dont use UClass, i cant choose one from Content folder.

Ahhh, silly me. One wrong letter and i created an undefined type.

// This was causing headache to me :smiley:

class UBlueprintGeneretedClass* ActorToBeSpawned;

Everything is going fine but BlueprintGeneratedClass.h gives lots of errors. Related to itself. All compiler errors are from BlueprintGeneratedClass.h

I have done nothing else but adding these lines.

What is it wrong that i did.

#include "Engine/BlueprintGeneratedClass.h"

...
...
// Pawn to be spawned
UPROPERTY(EditAnywhere, Category = Spawn)
UBlueprintGeneratedClass* ActorToBeSpawned;

Sorry, was at a restaurant. What you want is a TSubclassOf SpawnActor. That will be the class type, NOT a level actor.
Pointers always are for live objects(the “this” variable is active). You can use TSubclassOf to use the specific class within Unreal Engine.

You want to be able to set a BP that you have in your Content Folder as this SpawnActor variable?

Try

TSubclassOf<class AActor> SpawnActor

As myself and exi said, try using
TSubclassOf class AActor SpawnActor

Thanks for the help

Okay will try it out

Thanks for the help, it did worked