[C++] 3인칭 캐릭터 이동, 회전

Woogle·2022년 11월 16일
0

언리얼 엔진 5

목록 보기
28/60

📄 헤더

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "TPSPlayer.generated.h"

UCLASS()
class MYTPS_API ATPSPlayer : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ATPSPlayer();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	UPROPERTY(EditAnywhere)
	class USpringArmComponent* springArmComp;

	UPROPERTY(EditAnywhere)
	class UCameraComponent* cameraComp;

	void OnInputHorizontal(float value);
	void OnInputVertical(float value);
	void OnInputMouseX(float value);
	void OnInputMouseY(float value);
	void OnInputJump();

	FVector direction;
	float speed = 600.f;
};

📄 소스

#include "TPSPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"

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

	// 에셋 찾아오기
	ConstructorHelpers::FObjectFinder<USkeletalMesh> tempBody(TEXT("SkeletalMesh'/Game/Characters/Mannequins/Meshes/SKM_Quinn.SKM_Quinn'"));

	// 스켈레탈 메쉬 적용
	if (tempBody.Succeeded()) // nullptr이면 실행 안함
	{
		GetMesh()->SetSkeletalMesh(tempBody.Object);
		GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -90), FRotator(0, -90, 0));
	}

	// 스프링암, 카메라 배치
	springArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("springArmComp"));
	springArmComp->SetupAttachment(RootComponent);
	springArmComp->SetRelativeLocation(FVector(0, 50, 60));
	springArmComp->TargetArmLength = 120.f;
	cameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("cameraComp"));
	cameraComp->SetupAttachment(springArmComp);

	// 카메라 회전 설정
	bUseControllerRotationYaw = true;
	springArmComp->bUsePawnControlRotation = true;
	GetCharacterMovement()->bOrientRotationToMovement = false;
}

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

}

// Called every frame
void ATPSPlayer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 플레이어 이동
	direction = FTransform(GetControlRotation()).TransformVector(FVector::ZeroVector);	// 컨트롤러 Rotation을 로컬에서 월드로 Vector Transform
	AddMovementInput(direction);	// 컨트롤러 기준으로 벡터 계산
}

// Called to bind functionality to input
void ATPSPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// 축 입력 바인딩
	PlayerInputComponent->BindAxis(TEXT("Move Right / Left"), this, &ATPSPlayer::OnInputHorizontal);
	PlayerInputComponent->BindAxis(TEXT("Move Forward / Backward"), this, &ATPSPlayer::OnInputVertical);
	PlayerInputComponent->BindAxis(TEXT("Turn Right / Left Mouse"), this, &ATPSPlayer::OnInputMouseX);
	PlayerInputComponent->BindAxis(TEXT("Look Up / Down Mouse"), this, &ATPSPlayer::OnInputMouseY);

	// 액션 입력 바인딩
	PlayerInputComponent->BindAction(TEXT("Jump"), IE_Pressed, this, &ATPSPlayer::OnInputJump);
}

void ATPSPlayer::OnInputHorizontal(float value)
{
	direction.Y = value;	// 좌우 이동
}

void ATPSPlayer::OnInputVertical(float value)
{
	direction.X = value;	// 전후 이동
}

void ATPSPlayer::OnInputMouseX(float value)
{
	AddControllerYawInput(value);
}

void ATPSPlayer::OnInputMouseY(float value)
{
	AddControllerPitchInput(value);
}

void ATPSPlayer::OnInputJump()
{
	ACharacter::Jump();
}

📄 컨트롤러

AController : 컨트롤러 클래스에 입력값을 저장해놓고, 필요한 곳(Character Movement Component)에서 꺼내 사용하는 구조

  • 이동, 점프
  • 회전

✏️ 카메라 회전 설정

(TPS 게임 기준) 항상 카메라가 캐릭터의 정면 방향을 바라보게 한다.

  • Character : 사용자 입력(AController)이 들어오면 폰을 회전(Pitch, Yaw, Roll)시킬지
  • Spring Arm Component : 폰이 회전하면 스프링암 컴포넌트도 같이 회전시킬지
  • Camera Component
  • Character Movement Component
profile
노력하는 게임 개발자

0개의 댓글