Why does Unreal Engine crash when I call a method in a Pawn class from an Actor class

I am new to using C++ to code in Unreal Engine as a module for my university, what I have made so far is a space ship (SpaceShipPawn) that can shoot projectiles (ShipProjectile). When I fire the projectiles and they hit with something, they are supposed to call a method in the space ship pawn class, increment the int Score held in the pawn class, and print a debug message to the screen.

If I don’t call the method I am trying to call, the projectiles get destroyed like they are supposed to. Though when the projectiles hit anything when I include the method they cause Unreal Engine to freeze and become unresponsive. I am not sure what I am doing wrong, any help would be appreciated!

SpaceShipPawn.cpp

ASpaceShipPawn::ASpaceShipPawn()
{
	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	static ConstructorHelpers::FObjectFinder<UStaticMesh> ShipMesh(TEXT("/Game/Meshes/UFO.UFO"));
	ShipMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipMesh"));
	RootComponent = ShipMeshComponent;
	ShipMeshComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
	ShipMeshComponent->SetStaticMesh(ShipMesh.Object);

	CanFire = true;
	FireRate = 1.0f;
	GunOffset = 70.0f;
	Score = 0;
}

{…
Some more code for making the space ship work
…}

void ASpaceShipPawn::ScoreGained(){
	if (GEngine){
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Increment Score"));
	}
	Score++;
}

ShipProjectile.cpp

void AShipProjectile::OnHit(AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit){
	if (GEngine){
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Hit ->") + OtherActor ->GetName());
	}

	ASpaceShipPawn test;
	test.ScoreGained();

	Destroy();
}

Something that might help in general with this sort of stuff is running from the visual studio debugger. Instead of opening from the launcher, open your project’s .sln file, and hit play. This run the editor from the debugger and will break on crashes like this(so you know what line it crashed on, and what memory looks like at the time it crashed). You can also set break points.

Anyway, your problem is probably that you’re trying to create an actor incorrectly. An object that’s put on the stack(created without ‘new’) like you’ve done here, will be destroyed when it leaves scope(after you leave the {} where it was created). So, this wouldn’t work to begin with because you’re creating a space ship pawn that will immediately be destroyed. Actors have a lot of complex state and they should be created through the SpawnActor functions:

This will correctly create a new actor for you, and it will last until you call Destroy on it.

That might solve the crashing, but what I think you meant to do is take the space ship that owns the projectile that hit something, and call ScoreGained on that. For this you probably want to look into instigators. Instigators are pawns that are responsible for other actors(your space ship will be responsible for the projectiles it shoots.) An instigator can be set through the FActorSpawnParameters parameter of SpawnActor. You can then call GetInstigator on an actor to get the pawn who’s responsible for it.

ASpaceShipPawn test;
test.ScoreGained();

This is wrong. You need to access a pointer to your pawn, not create a new pawn object.
an example on doing this would be:

if (GetWorld != nullptr && GetWorld()->GetFirstPlayerController() != nullptr)
{
	ASpaceShipPawn* PawnPtr = Cast<ASpaceShipPawn>(GetWorld()->GetFirstPlayerController()->GetPawn());
	if (PawnPtr != nullptr)
	{
		PawnPtr->ScoreGained();
	}
}

Ah, thank you!

Thank you for the detailed response :slight_smile: I will definitely be looking into instigators