본문 바로가기

Unreal Engine 4/C++

<Unreal C++> 8 - Player

필요한 개념

 


플레이어는 BP와 마찬가지로 ACharacter로 부터 상속받아 구현한다.

CPlayer 클래스 생성(ACharacter 상속받는)


Tip) C를 접두사로 붙이는 이유는 -> unreal에 있는 클래스와 구분하기 위해


기본적인 #include 헤더 설명
#include "CoreMinimal.h"
#include "GameFramework/Character.h" -> 여기에는 자기가 상속받을 클래스가 나온다.
#include "CPlayer.generated.h" -> GENERATED_BODY()에 대한 헤더를 가짐(UCLASS()가 붙을때만 나옴)

UCLASS() -> 즉, 언리얼에서 사용할 클래스 임을 명시
class UONLINE_03_CPP_API ACPlayer : public ACharacter
{
GENERATED_BODY() -> 블루프린트에 들어갈려면 어떤 코드가 필요한데, 그 코드들을 대체해주는 매크로
}

CoreMinimal.h : 언리얼에서 필수적으로 사용될 클래스들이 모여있는 헤더(ex) 수학 클래스 같은 기본적 클래스)
generated.h, UCLASS(), GENERATED_BODY() 모두 하나의 쌍
UCLASS()는 BP에서도 이 클래스를 사용할 수 있다는 의미(통신상의 의미), 얘를 기반으로 BP생성가능한 이유가 이 키워드 때문

UCLASS()에 ALT + E해서 보면 Blueprintable(블루프린트 이벤트등 얘로 블루프린트화 할 수있다는것), BlueprintType(블루프린트 타입으로 다룰 수 있다.)
이 두개 체크시에 블루프린트 자체로 다룰 수 있다.(상속 안받고도) 잘 안씀...

UCLASS()
class UONLINE_03_CPP_API ACPlayer : public ACharacter
{
이 부분
GENERATED_BODY()

1. class와 GENERATED_BODY() 사이에는 어떠한 코드도 들어가면 안된다.
why? 사이에 코드가 들어가면 GENERATED_BODY() 매크로랑 코드가 섞인다.


#include ""

이 부분

UCLASS()
class UONLINE_03_CPP_API ACPlayer : public ACharacter
2. 헤더와 class선언 위에 부분에는 무언가 들어갈 수 있지만, 델리게이션 부분, 구조체 선언 밖에 거의 안들어감

기본적으로 ACharacter를 상속받아 cpp를 생성하면
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;가 들어가 있다.
SetupPlayerInputComponent : 플레이어의 입력을 받아 우리가 원하는대로 처리할 수 있도록 하는 함수
(ex) PlayerController가 있다면 이 함수를 무시한다, 우리는 현재 Controller를 쓰지 않아서 이 함수를 통해 입력을 받아올 것임)


항상 프로그램팀은 기본값을 하나 설정해주고 필요시 다른 팀에서 다른 값으로 변경해서 쓰도록 해준다.
(ex) 캐릭터를 하나를 넣어놓고 디자인팀에서 알아서 세팅함)



* CPlayer.cpp 참고 이미지

 

 

컴포넌트 추가 및 부모자식관계 세팅

 

SkeletalMesh 기본 메쉬 설정 및 트랜스폼 회전

 

 

CPlayer.h


더보기
#pragma once

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

UCLASS()
class UONLINE_03_CPP_API ACPlayer : public ACharacter
{
	GENERATED_BODY()

private:
	// 비추는 카메라랑 간격을 설정하기 위해 SpringArm 필요
	UPROPERTY(VisibleDefaultsOnly)
		class USpringArmComponent* SpringArm;

	// 카메라를 담당하는 컴포넌트
	UPROPERTY(VisibleDefaultsOnly)
		class UCameraComponent* Camera;

public:
	ACPlayer();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

 

 

 

 

 

 

 

CPlayer.cpp


더보기
#include "CPlayer.h"
#include "Global.h"
#include "GameFramework/SpringArmComponent.h" // SpringArm 컴포넌트의 위치
#include "GameFramework/CharacterMovementComponent.h" // CharacterMovement컴포넌트 사용을 위한
#include "Camera/CameraComponent.h" // 카메라 컴포넌트의 위치
#include "Components/CapsuleComponent.h" // 캡슐컴포넌트의 위치

ACPlayer::ACPlayer()
{
 	PrimaryActorTick.bCanEverTick = true;

	// CreateDefaultSubobject() : 컴포넌트 만들때 항상 이 함수 씀
	// 이전에는 mesh에 붙여주었지만, 지금은 CapsuleComponent에 붙임
	// 나중에 건슈팅 모드할때 더 편하다.
	// 캐릭터의 기본은 CapsuleComponent가 있다.
	
	
	//SpringArm = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
	//SpringArm->SetupAttachment(GetCapsuleComponent());
	//
	//Camera = CreateDefaultSubobject<UCameraComponent>("Camera");
	//// 스프링암에 카메라를 붙여 넣음
	//Camera->SetupAttachment(SpringArm);

	// Capsule 컴포넌트에 붙일 것임
	CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetCapsuleComponent());
	// 스프링암에 카메라를 붙여 넣음
	CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);

	// bUseControllerRotationYaw
	// 이 코드는 캐릭터가 카메라의 회전을 따라서 회전하지 않도록 한다.
	bUseControllerRotationYaw = false;
	// 이동하는 방향으로 회전
	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->MaxWalkSpeed = 400.0f; // 기본 속도

	// 에셋 가져오고
	USkeletalMesh* mesh;
	CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
	// SkeletalMesh 세팅
	GetMesh()->SetSkeletalMesh(mesh);

	// SkeletalMesh의 위치와 회전을 기본값으로 넣어주기 위해
	// 생성자에 값을 설정해준다.
	// SetRelativeLocation : 상대위치 세팅
	// SetRelativeLocation : 상대위치 세팅
	GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
	// 우리는 Yaw(수직회전)해야 하기 때문에, Yaw(가운데) 세팅
	// BP상에서 회전 x,y,z는 Roll, Pitch, Yaw 다.
	// C에서랑 혼동주의
	GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
}

void ACPlayer::BeginPlay()
{
	Super::BeginPlay();
	
}

void ACPlayer::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

 

 

Helpers.h 추가된 내용


더보기
class UONLINE_03_CPP_API CHelpers
{
   ...
public:
	// 1 : 어느 액터에 붙을 컴포넌트냐? 2 : 생성해서 붙여서 리턴할 컴포넌트, 3: 변수명, 4 : Actor컴포넌트가 최상위 컴포넌트 인데, Transform이 추가된 것(부모,자식 관계를 갖는애)이 SceneComponent이다. NULL이면 루트로감
	template<typename T>
	static void CreateComponent(AActor* InActor, T** InComponent, FName InName, USceneComponent* InParent = NULL)
	{
		*InComponent = InActor->CreateDefaultSubobject<T>(InName);

		// Parent가 NULL이 아니라면
		if (!!InParent)
		{
			(*InComponent)->SetupAttachment(InParent);

			return;
		}

		// NULL이라면 부모가 없는것이다.
		// 부모가 없다면 InComponent가 루트가 됨
		InActor->SetRootComponent((*InComponent));
	}
}

 

 

 

 

 

 

 

 

결과


'Unreal Engine 4 > C++' 카테고리의 다른 글

<Unreal C++> 10 - UAnimInstance  (0) 2022.04.07
<Unreal C++> 9 - PlayerInputComponent  (0) 2022.04.04
<Unreal C++> 7 - Material  (0) 2022.04.04
<Unreal C++> 4 - Actor Spawn  (0) 2022.04.04
<Unreal C++> 2 - C++과 BP 통신  (0) 2022.03.30