플레이어
캐릭터 클래스로 CPlayer 생성
헤더
SpringArmComponent와 CameraComponent, Input값에 바인딩될 함수와 연결할 InputComponent 추가
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "CPlayer.generated.h"
UCLASS()
class U03_BASIC_API ACPlayer : public ACharacter
{
GENERATED_BODY()
private:
UPROPERTY(VisibleAnywhere)
class USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere)
class UCameraComponent* Camera;
public:
ACPlayer();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
// 인풋에 바인딩 된 함수 콜
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
소스
포함할 헤더
#include "CPlayer.h"
#include "Global.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
Character 초기 구성과 특징 정의해주기
ACPlayer::ACPlayer()
{
PrimaryActorTick.bCanEverTick = true;
// 스프링암, 카메라 붙이기
CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetCapsuleComponent());
SpringArm->SetRelativeLocation(FVector(0, 0, 60));
SpringArm->TargetArmLength = 200.0f;
CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
// 스켈레탈메시 붙이기
USkeletalMesh* mesh;
CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
GetMesh()->SetSkeletalMesh(mesh);
GetMesh()->SetRelativeLocation(FVector(0, 0, -90)); // 중심 위치에서 90 밑으로 내려주기
GetMesh()->SetRelativeRotation(FRotator(0, -90, 0)); // CPP = Y(Pitch) Z(Yaw) X(Roll) / BP = X(Roll) Y(Pitch) Z(Yaw)
// 캐릭터 회전 & 카메라 움직임 Set
this->bUseControllerRotationYaw = false;
GetCharacterMovement()->bOrientRotationToMovement = true;
SpringArm->bUsePawnControlRotation = true;
SpringArm->bEnableCameraLag = true;
}
void ACPlayer::BeginPlay()
{
Super::BeginPlay();
}
void ACPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
}
C++에서의 FRotator 순서는 Y(Pitch) Z(Yaw) X(Roll) 순서이다 - BP에서는 X(Roll) Y(Pitch) Z(Yaw) 순
Cplayer기반 블루프린트 클래스 생성해서 GameModeBase에 Default Pawn으로 설정해둘 BP_CPlayer를 만들어 두자
GameModeBase
CPlayer클래스가 생성됐으니 GameModeBase에 DefaultPawnClass으로 Set해줘야 한다
그 전에 몇가지 더 실험해 보기
클래스 이름 바꿔보기
자동으로 생성되어있는 GameModeBase의 이름을 임의로 바꿀때 수정해야 할 것들 확인하기
총 3개 : generated 헤더, 클래스명, 클래스 헤더명 바꿔주기
이름이 바뀐 GameModeBase클래스는 기존 GameModeBase가 남아있는 채로 별도로 언리얼 컨텐츠브라우저에 표시되고, C++ 에서는 시간이지나면(컴파일 완료되면) 자동으로 소스와 헤더가 다시 생성된다
프로젝트셋팅 > 맵&모드에 CGameMode로 변경 적용!
생성자
생성자에서 Default Pawn Class에 BP_CPlayer로 Set해주기
public:
ACGameMode();
ACGameMode::ACGameMode()
{
CHelpers::GetClass<APawn>(&DefaultPawnClass, "Blueprint'/Game/BP_CPlayer.BP_CPlayer_C'"); // 경로 마지막에 _C를 포함해줘야 한다
}
C++ 클래스를 부모클래스로 가진 블루프린트 클래스들은 경로로 참조할 때 ‘전에 _C를 포함해 줘야 한다
혹시 C++ 클래스를 부모클래스로 갖는 블루프린트클래스에 변경사항이 적용되지 않았다면,
우클릭 > 에셋 액션 > 리로드를 통해 클래스 초기화를 시켜줄 수 있다. 단, 블프에만 별도로 적용한 내용이 있다면 모두 사라지니 주의하기!
유효성 Check매크로
블루프린트에서 isValid를 사용하듯 CHelpers에 유효성 확인을 하는 매크로를 만들어보자
#define CheckTrue(x) {if(x==true) return;}
#define CheckTrueResult(x,y) {if(x==true) return y;}
#define CheckFalse(x) {if(x==false) return;}
#define CheckFalseResult(x,y) {if(x==false) return y;}
#define CheckNull(x) {if(x==nullptr) return;}
#define CheckNullResult(x,y) {if(x==nullptr) return y;}
애니메이션
애니메이션 블루프린트도 C++로 생성해보자
AnimInstance를 부모로 갖는 C++클래스 CAnimInstance를 생성하기 (초기 리스트에 안보이니 모든클래스 표시 체크 후 검색!)
애니메이션 블루프린트에서와 같이 BeginPlay와 Update를 구현하지만, C++에선
NativeBeginPlay와
NativeUpdateAnimation을 사용한다. 부모클래스AnimInstance로 부터override하기
헤더
OwnerCharacter와 Speed값 Set해주기
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "CAnimInstance.generated.h"
UCLASS()
class U03_BASIC_API UCAnimInstance : public UAnimInstance
{
GENERATED_BODY()
protected:
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Animation")
float Speed;
public:
void NativeBeginPlay() override;
void NativeUpdateAnimation(float DeltaSeconds) override;
private:
class ACharacter* OwnerCharacter;
};
소스
#include "CAnimInstance.h"
#include "Global.h"
#include "GameFramework/Character.h"
void UCAnimInstance::NativeBeginPlay()
{
Super::NativeBeginPlay();
OwnerCharacter = Cast<ACharacter>(TryGetPawnOwner());
}
void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
CheckNull(OwnerCharacter); // CHelpers 유효성체크 매크로
Speed = OwnerCharacter->GetVelocity().Size2D(); // GetVelocity > VectorLength (Kismet Math Library에있는 함수)
}
애니메이션 블루프린트
CAnimInstance클래스를 기반으로 하는 블루프린트클래스 생성을 통해 만드는 ABP에는 AnimGraph가 없기 때문에
우선 언리얼 컨텐츠브라우저에 직접 애니메이션 블루프린트를 생성하고 부모클래스를 CAnimInstance로 선택한다
CHelpers::GetClass
CHelpers에 ClassFinder를 통해 Class를 Get하는 함수 템플릿을 만들자
template<typename T>
static void GetClass(TSubclassOf<T>* OutObject, FString InPath)
{
ConstructorHelpers::FClassFinder<T> asset(*InPath);
*OutObject = asset.Class;
}
애니메이션 클래스 추가
아래 내용을 CPlayer.cpp생성자에 추가해주기
// 캐릭터 애니메이션
TSubclassOf<UCAnimInstance> animInstance;
CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_CCharacter.ABP_CCharacter_C'");
GetMesh()->SetAnimClass(animInstance);
// 캐릭터 속도
GetCharacterMovement()->MaxWalkSpeed = 400.0f;