UE4 C++ 캐릭터 애니메이션


Tags :


플레이어

캐릭터 클래스로 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) 순

15

Cplayer기반 블루프린트 클래스 생성해서 GameModeBase에 Default Pawn으로 설정해둘 BP_CPlayer를 만들어 두자


GameModeBase

CPlayer클래스가 생성됐으니 GameModeBase에 DefaultPawnClass으로 Set해줘야 한다
그 전에 몇가지 더 실험해 보기

클래스 이름 바꿔보기

자동으로 생성되어있는 GameModeBase의 이름을 임의로 바꿀때 수정해야 할 것들 확인하기
16

총 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를 포함해 줘야 한다

17

혹시 C++ 클래스를 부모클래스로 갖는 블루프린트클래스에 변경사항이 적용되지 않았다면,
우클릭 > 에셋 액션 > 리로드를 통해 클래스 초기화를 시켜줄 수 있다. 단, 블프에만 별도로 적용한 내용이 있다면 모두 사라지니 주의하기!
18


유효성 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를 생성하기 (초기 리스트에 안보이니 모든클래스 표시 체크 후 검색!)
19

애니메이션 블루프린트에서와 같이 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로 선택한다
20

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;

UE4_CPP_003