202 lines
8.5 KiB
C++
Executable File
202 lines
8.5 KiB
C++
Executable File
// Fill out your copyright notice in the Description page of Project Settings.
|
|
#include "MyDefaultPawn.h"
|
|
|
|
#include "UObject/ConstructorHelpers.h"
|
|
#include "Engine/World.h"
|
|
#include "Components/StaticMeshComponent.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "Engine/CollisionProfile.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Components/SphereComponent.h"
|
|
#include "GameFramework/PawnMovementComponent.h"
|
|
#include "GameFramework/FloatingPawnMovement.h"
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
|
#include "GameFramework/PlayerInput.h"
|
|
|
|
FName AMyDefaultPawn::MovementComponentName(TEXT("MovementComponent0"));
|
|
FName AMyDefaultPawn::CollisionComponentName(TEXT("CollisionComponent0"));
|
|
FName AMyDefaultPawn::MeshComponentName(TEXT("MeshComponent0"));
|
|
|
|
|
|
AMyDefaultPawn::AMyDefaultPawn(const FObjectInitializer& ObjectInitializer) : APawn(ObjectInitializer)
|
|
{
|
|
SetCanBeDamaged(true);
|
|
|
|
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
|
|
bReplicates = true;
|
|
NetPriority = 3.0f;
|
|
|
|
BaseEyeHeight = 0.0f;
|
|
bCollideWhenPlacing = false;
|
|
SpawnCollisionHandlingMethod = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
|
|
|
CollisionComponent = CreateDefaultSubobject<USphereComponent>(AMyDefaultPawn::CollisionComponentName);
|
|
CollisionComponent->InitSphereRadius(35.0f);
|
|
CollisionComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
|
|
|
|
CollisionComponent->CanCharacterStepUpOn = ECB_No;
|
|
CollisionComponent->SetShouldUpdatePhysicsVolume(true);
|
|
CollisionComponent->SetCanEverAffectNavigation(false);
|
|
CollisionComponent->bDynamicObstacle = true;
|
|
|
|
RootComponent = CollisionComponent;
|
|
|
|
MovementComponent = CreateDefaultSubobject<UPawnMovementComponent, UCharacterMovementComponent>(AMyDefaultPawn::MovementComponentName);
|
|
MovementComponent->UpdatedComponent = CollisionComponent;
|
|
|
|
// Structure to hold one-time initialization
|
|
struct FConstructorStatics
|
|
{
|
|
ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh;
|
|
FConstructorStatics()
|
|
: SphereMesh(TEXT("/Engine/EngineMeshes/Sphere")) {}
|
|
};
|
|
|
|
static FConstructorStatics ConstructorStatics;
|
|
|
|
MeshComponent = CreateOptionalDefaultSubobject<UStaticMeshComponent>(AMyDefaultPawn::MeshComponentName);
|
|
if (MeshComponent)
|
|
{
|
|
MeshComponent->SetStaticMesh(ConstructorStatics.SphereMesh.Object);
|
|
MeshComponent->AlwaysLoadOnClient = true;
|
|
MeshComponent->AlwaysLoadOnServer = true;
|
|
MeshComponent->bOwnerNoSee = true;
|
|
MeshComponent->bCastDynamicShadow = true;
|
|
MeshComponent->bAffectDynamicIndirectLighting = false;
|
|
MeshComponent->bAffectDistanceFieldLighting = false;
|
|
MeshComponent->bVisibleInRayTracing = false;
|
|
MeshComponent->PrimaryComponentTick.TickGroup = TG_PrePhysics;
|
|
MeshComponent->SetupAttachment(RootComponent);
|
|
MeshComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
|
|
const float Scale = CollisionComponent->GetUnscaledSphereRadius() / 160.f; // @TODO: hardcoding known size of EngineMeshes.Sphere. Should use a unit sphere instead.
|
|
MeshComponent->SetRelativeScale3D(FVector(Scale));
|
|
MeshComponent->SetGenerateOverlapEvents(false);
|
|
MeshComponent->SetCanEverAffectNavigation(false);
|
|
}
|
|
|
|
// This is the default pawn class, we want to have it be able to move out of the box.
|
|
bAddDefaultMovementBindings = true;
|
|
}
|
|
|
|
void InitializeDefaultPawnInputBindings()
|
|
{
|
|
static bool bBindingsAdded = false;
|
|
if (!bBindingsAdded)
|
|
{
|
|
bBindingsAdded = true;
|
|
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveForward", EKeys::W, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveForward", EKeys::S, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveForward", EKeys::Up, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveForward", EKeys::Down, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveForward", EKeys::Gamepad_LeftY, 1.f));
|
|
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveRight", EKeys::A, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveRight", EKeys::D, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveRight", EKeys::Gamepad_LeftX, 1.f));
|
|
|
|
// HACK: Android controller bindings in ini files seem to not work
|
|
// Direct overrides here some to work
|
|
#if !PLATFORM_ANDROID
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Gamepad_LeftThumbstick, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Gamepad_RightThumbstick, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Gamepad_FaceButton_Bottom, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::LeftControl, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::SpaceBar, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::C, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::E, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Q, -1.f));
|
|
#else
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Gamepad_LeftTriggerAxis, -0.5f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_MoveUp", EKeys::Gamepad_RightTriggerAxis, 0.5f));
|
|
#endif
|
|
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_TurnRate", EKeys::Gamepad_RightX, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_TurnRate", EKeys::Left, -1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_TurnRate", EKeys::Right, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_Turn", EKeys::MouseX, 1.f));
|
|
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_LookUpRate", EKeys::Gamepad_RightY, 1.f));
|
|
UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("DefaultPawn_LookUp", EKeys::MouseY, -1.f));
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
|
{
|
|
check(PlayerInputComponent);
|
|
|
|
if (bAddDefaultMovementBindings)
|
|
{
|
|
InitializeDefaultPawnInputBindings();
|
|
|
|
PlayerInputComponent->BindAxis("DefaultPawn_MoveForward", this, &AMyDefaultPawn::MoveForward);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_MoveRight", this, &AMyDefaultPawn::MoveRight);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_MoveUp", this, &AMyDefaultPawn::MoveUp_World);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_Turn", this, &AMyDefaultPawn::AddControllerYawInput);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_TurnRate", this, &AMyDefaultPawn::TurnAtRate);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_LookUp", this, &AMyDefaultPawn::AddControllerPitchInput);
|
|
PlayerInputComponent->BindAxis("DefaultPawn_LookUpRate", this, &AMyDefaultPawn::LookUpAtRate);
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::UpdateNavigationRelevance()
|
|
{
|
|
if (CollisionComponent)
|
|
{
|
|
CollisionComponent->SetCanEverAffectNavigation(bCanAffectNavigationGeneration);
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::MoveRight(float Val)
|
|
{
|
|
if (Val != 0.f)
|
|
{
|
|
if (Controller)
|
|
{
|
|
FRotator const ControlSpaceRot = Controller->GetControlRotation();
|
|
|
|
// transform to world space and add it
|
|
AddMovementInput(FRotationMatrix(ControlSpaceRot).GetScaledAxis(EAxis::Y), Val);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::MoveForward(float Val)
|
|
{
|
|
if (Val != 0.f)
|
|
{
|
|
if (Controller)
|
|
{
|
|
FRotator const ControlSpaceRot = Controller->GetControlRotation();
|
|
|
|
// transform to world space and add it
|
|
AddMovementInput(FRotationMatrix(ControlSpaceRot).GetScaledAxis(EAxis::X), Val);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::MoveUp_World(float Val)
|
|
{
|
|
if (Val != 0.f)
|
|
{
|
|
AddMovementInput(FVector::UpVector, Val);
|
|
}
|
|
}
|
|
|
|
void AMyDefaultPawn::TurnAtRate(float Rate)
|
|
{
|
|
// calculate delta for this frame from the rate information
|
|
AddControllerYawInput(Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
|
|
}
|
|
|
|
void AMyDefaultPawn::LookUpAtRate(float Rate)
|
|
{
|
|
// calculate delta for this frame from the rate information
|
|
AddControllerPitchInput(Rate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation);
|
|
}
|
|
|
|
UPawnMovementComponent* AMyDefaultPawn::GetMovementComponent() const
|
|
{
|
|
return MovementComponent;
|
|
}
|