I just tried to make my own Pawn class by inheriting the default APawn class. Then I made a blueprint from that class and put it as my standard Pawn BP in my gamemode. When I press Play, the editor immediately crashes with this log:
Access violation - code c0000005 (first/second chance not available)
UE4Editor_BuildingEscape_1650!ABuildingEscapePawn::SetupInputComponent() [e:\ue4 projects\03_buildingescape\buildingescape\source\buildingescape\buildingescapepawn.cpp:38]
UE4Editor_Engine!APawn::PawnClientRestart() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\pawn.cpp:367]
UE4Editor_Engine!APlayerController::ClientRestart_Implementation() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:719]
UE4Editor_Engine!APlayerController::execClientRestart() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\classes\gameframework\playercontroller.h:155]
UE4Editor_CoreUObject!UFunction::Invoke() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\class.cpp:5077]
UE4Editor_CoreUObject!UObject::ProcessEvent() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:1245]
UE4Editor_Engine!AActor::ProcessEvent() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\actor.cpp:639]
UE4Editor_Engine!APlayerController::ClientRestart() [d:\build\++ue4+release-4.12+compile\sync\engine\intermediate\build\win64\ue4editor\inc\engine\engine.generated.1.cpp:4367]
UE4Editor_Engine!APlayerController::Possess() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:785]
UE4Editor_Engine!AGameMode::RestartPlayer() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\gamemode.cpp:501]
UE4Editor_Engine!AGameMode::HandleMatchHasStarted() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\gamemode.cpp:607]
UE4Editor_Engine!AGameMode::SetMatchState() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\gamemode.cpp:733]
UE4Editor_Engine!AGameMode::StartMatch() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\gamemode.cpp:600]
UE4Editor_Engine!UWorld::BeginPlay() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\world.cpp:3218]
UE4Editor_Engine!UGameInstance::StartPIEGameInstance() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\engine\private\gameinstance.cpp:293]
UE4Editor_UnrealEd!UEditorEngine::CreatePIEGameInstance() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\playlevel.cpp:3250]
UE4Editor_UnrealEd!UEditorEngine::PlayInEditor() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\playlevel.cpp:2346]
UE4Editor_UnrealEd!UEditorEngine::StartQueuedPlayMapRequest() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\playlevel.cpp:1103]
UE4Editor_UnrealEd!UEditorEngine::Tick() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\editorengine.cpp:1246]
UE4Editor_UnrealEd!UUnrealEdEngine::Tick() [d:\build\++ue4+release-4.12+compile\sync\engine\source\editor\unrealed\private\unrealedengine.cpp:368]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:2775]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launch.cpp:148]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
UE4Editor!WinMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:200]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:264]
kernel32
ntdll
I need help figuring out why this happens. On line 38 in buildingescapepawn.cpp you find this:
InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();
I’m still learning C++ so please bear with me
And here is my code:
ABuildingEscapePawn.h
#pragma once
#include "GameFramework/Pawn.h"
#include "BuildingEscapePawn.generated.h"
UCLASS()
class BUILDINGESCAPE_API ABuildingEscapePawn : public APawn
{
GENERATED_BODY()
public:
// How far ahead of the player can we reach in cm
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Reach = 100.f;
// Sets default values for this pawn's properties
ABuildingEscapePawn();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
private:
UPhysicsHandleComponent* PhysicsHandle = nullptr;
UInputComponent* InputComponent = nullptr;
/*---------------*/
/* Input Section */
/*---------------*/
// Ray-cast and use what's in reach
void Use();
// Ray-cast and grab what's in reach
void Grab();
// Called when grab key is released
void ReleaseGrab();
/*-----------------*/
/* Helper Functions*/
/*-----------------*/
// Find attached physics handle
void FindPhysicsHandleComponent();
// Return hit for first physics body in reach
const FHitResult GetFirstPhysicsBodyInReach();
// Return hit for first use handle in reach
const FHitResult GetFirstUseHandleInReach();
// Setup (assumed) attached input component
void SetupInputComponent();
// Find the vector at the start of the players reach
FVector GetReachLineStart();
// Find the vector at the end of the players reach
FVector GetReachLineEnd();
};
ABuildingEscapePawn.cpp
#include "BuildingEscape.h"
#include "BuildingEscapePawn.h"
#include "UseComponent.h"
// Sets default values
ABuildingEscapePawn::ABuildingEscapePawn()
{
// 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;
}
// Called when the game starts or when spawned
void ABuildingEscapePawn::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ABuildingEscapePawn::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
// Called to bind functionality to input
void ABuildingEscapePawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
Super::SetupPlayerInputComponent(InputComponent);
SetupInputComponent();
}
void ABuildingEscapePawn::SetupInputComponent()
{
InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();
if (InputComponent)
{
InputComponent->BindAction("Use", EInputEvent::IE_Pressed, this, &ABuildingEscapePawn::Use);
InputComponent->BindAction("Grab", EInputEvent::IE_Pressed, this, &ABuildingEscapePawn::Grab);
InputComponent->BindAction("Grab", EInputEvent::IE_Released, this, &ABuildingEscapePawn::ReleaseGrab);
}
else
{
UE_LOG(LogTemp, Error, TEXT("%s missing input component"), *(GetOwner()->GetName()));
}
}
void ABuildingEscapePawn::Use()
{
if (!PhysicsHandle->GrabbedComponent)
{
FHitResult HitResult = GetFirstUseHandleInReach();
AActor* ActorHit = HitResult.GetActor();
if (ActorHit)
{
UUseComponent* UseComp = ActorHit->FindComponentByClass<UUseComponent>();
if (UseComp)
{
UseComp->FireUseEvent();
}
}
}
}
void ABuildingEscapePawn::Grab()
{
/// Line trace and see if we reach any actors with physics body collision channel set
FHitResult HitResult = GetFirstPhysicsBodyInReach();
UPrimitiveComponent* ComponentToGrab = HitResult.GetComponent();
AActor* ActorHit = HitResult.GetActor();
/// If we hit something, then attach a physics handle
if (ActorHit && PhysicsHandle)
{
PhysicsHandle->GrabComponent(ComponentToGrab, EName::NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), true); // true is to allow rotation
}
}
void ABuildingEscapePawn::ReleaseGrab()
{
PhysicsHandle->ReleaseComponent();
}
void ABuildingEscapePawn::FindPhysicsHandleComponent()
{
PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
if (PhysicsHandle == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("%s missing physics handle component"), *(GetOwner()->GetName()));
}
}
const FHitResult ABuildingEscapePawn::GetFirstUseHandleInReach()
{
/// Line-trace (AKA ray-cast) out to reach
FHitResult HitResult;
// Setup Query parameters
FCollisionQueryParams TraceParameters(FName(TEXT("")), false, GetOwner());
GetWorld()->LineTraceSingleByChannel(HitResult, GetReachLineStart(), GetReachLineEnd(), ECollisionChannel::ECC_Visibility, TraceParameters);
return HitResult;
}
const FHitResult ABuildingEscapePawn::GetFirstPhysicsBodyInReach()
{
/// Line-trace (AKA ray-cast) out to reach
FHitResult HitResult;
// Setup query parameters
FCollisionQueryParams TraceParameters(FName(TEXT("")), false, GetOwner());
GetWorld()->LineTraceSingleByObjectType(OUT HitResult, GetReachLineStart(), GetReachLineEnd(), FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody), TraceParameters);
return HitResult;
}
FVector ABuildingEscapePawn::GetReachLineStart()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT PlayerViewPointLocation, OUT PlayerViewPointRotation);
return PlayerViewPointLocation;
}
FVector ABuildingEscapePawn::GetReachLineEnd()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT PlayerViewPointLocation, OUT PlayerViewPointRotation);
return PlayerViewPointLocation + (PlayerViewPointRotation.Vector() * Reach);
}