오늘은 폰과 캐릭터의 차이를 보고, 폰과 캐릭터로 각각 플레이어 캐릭터를 만들어보겠다
순서는
이다
폰과 캐릭터는 모두 언리얼 엔진에서 제공하는 액터이고 폰은 유저가 컨트롤하는 물체,
캐릭터는 폰을 상속받아 움직이는 캐릭터형 액터이다
그렇기 때문에 캐릭터는 기본적으로 충돌을 체크해주는 CapsuleComponent
, 뼈대를 이루는 SkeletalMesh
,
이동을 제어하는 CharacterMovement
컴포넌트를 보유하고 있다
- UE5에서는 중력의 영향을 받지 않는
FloatingPawnMovement
와 중력의 영향을 받는CharacterMovement
2가지 이동방식을 제공한다
먼저 오늘 필요한 에셋은 모델링과 애니메이션에서 받을 수 있다
애니메이션은 resource폴더의 chapter5 폴더 안에 있다
모델링은 에픽런처를 통해 import 해주면 되고, 애니메이션은 컨텐츠 브라우저 창에 import
기능을 통해 추가해주자
블루프린트 없이도 애니메이션을 실행 시킬 수 있지만, 편의를 위해 이번 한번만 블루프린트를 쓰도록 하겠다
우클릭 후 Animation -> Animation BluePrint 를 통해 애니메이션 블루프린트를 만들어주고 이름을 짓는다
블루프린트를 열어 오른쪽 하단에 warriorRun
애니메이션을 블루프린트 창으로 끌어다 놓는다
이후 사람 모양을 이어주면 완성된다
현재는 이동여부와 관계없이 일단은 이동하는 것에 초점을 둘 것이다
Loop Animation이 체크되어 있지 않다면 체크하는것을 잊지 말자
마지막으로 컴파일 후 저장을 하게 되면 움직이고 있는 캐릭터의 모습을 볼 수 있다
이제 실제로 폰이 움직이게끔 해보자
폰에게 캡슐, 스켈레톤 메쉬, 무브먼트, 카메라암, 카메라를 컴포넌트로 달아주도록 하겠다
캐릭터는 기본적으로 CharacterMovement
가 있으니 폰은 FloatingPawnMovement
를 달아주도록 하겠다
먼저 헤더를 추가해주고
각각의 컴포넌트를 추가 시켜 주었다
아래는 cpp파일에서의 선언이다
1일차와 2일차에 했던 선언 과정을 동일하게 수행해준다
*워리어 모델링은 원하는 것을 아무거나 해도 상관이 없다
AABPawn::AABPawn()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
Capsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CAPSULE"));
Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MESH"));
Movement = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("MOVEMENT"));
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SPRINGARM"));
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("CAMERA"));
RootComponent = Capsule;
Mesh ->SetupAttachment(Capsule);
SpringArm->SetupAttachment(Capsule);
Camera ->SetupAttachment(SpringArm);
Capsule ->SetCapsuleHalfHeight(80.0f);
Capsule ->SetCapsuleRadius(34.0f);
Mesh ->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, -88.0f), FRotator(0.0f, -90.0f, 0.0f));
SpringArm->TargetArmLength = 400.0f;
SpringArm->SetRelativeRotation(FRotator(-15.0f, 0.0f, 0.0f));
Mesh->SetAnimationMode(EAnimationMode::AnimationBlueprint);
static ConstructorHelpers::FClassFinder<UAnimInstance> WARRIOR_ANIM
(TEXT("/Game/InfinityBladeWarriors/Character/Animations/WarriorAnimBlueprint.WarriorAnimBlueprint_C"));
if (WARRIOR_ANIM.Succeeded())
Mesh->SetAnimInstanceClass(WARRIOR_ANIM.Class);
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_CARDBOARD
(TEXT("/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Cardboard.SK_CharM_Cardboard"));
if (SK_CARDBOARD.Succeeded())
Mesh->SetSkeletalMesh(SK_CARDBOARD.Object);
}
여기까지 왔다면 이제 게임 실행 시 움직이는 모션을 가진 캐릭터가 나오게 된다
다만 아직 입력을 받아 움직이지는 못하는 상황이다
입력을 받기 위해 Edit - project setting - input으로 가자
Axis Mapping 에서 원하는 w,s는 앞뒤, a,d 는 좌우로 움직이도록 매핑을 설정해준다
헤더 파일에 매핑한 이름과 동일한 함수를 만들고, 이를 cpp 상에 선언해준다
이동과 관련된 요소의 바인딩은 SetupPlayerInputController
함수에 추가를 해주면 된다
BindAxis
를 통해 바인딩을 할 수 있다
이후 선언해준 UpDown 함수와 LeftRight 함수에는 AddMovement 함수를 통해 이동을 구현해준다
GetActorForwardVector
는 액터의 정면방향을 리턴해준다
좌우 이동에는 오른쪽 방향을 리턴해주는GetActorRightVector
를 사용한다
여기까지 왔다면 이동하는 캐릭터를 볼 수 있다
에디터에서 플레이 버튼을 누를 때마다 게임 화면을 클릭해야 입력이 되는 것이 불편하다면
간단한 코드를ABPlayerController
클래스에 추가해주도록 하자
헤더에서 BeginPlay 함수를 재정의해주고
cpp 파일에서 선언을 해주자
게임을 시작하면 마우스가 기본적으로 게임 안에 들어가 있는 상태가 된다
캐릭터는 기본적으로
Capsule
,ASkeletalMesh
,CharacterMovement
컴포넌트를 보유하고 있다
따라서 이들의 컴포넌트는 추가해줄 필요가 없고, 다만 Get~ 함수를 써서 인자를 받아오면 된다
아래는 h파일의 선언부이다
추가적으로 마우스의 회전을 받는 Turn 함수와 LookUp 함수를
Input창에서 만든 후 추가해 주도록 하자
아래는 cpp 파일의 선언부이다
// Sets default values
AABCharacter::AABCharacter()
{
// 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;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SPRINGARM"));
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("CAMERA"));
SpringArm->SetupAttachment(GetCapsuleComponent());
Camera ->SetupAttachment(SpringArm);
GetMesh()->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, -88.0f), FRotator(0.0f, -90.0f, 0.0f));
SpringArm->TargetArmLength = 400.0f;
SpringArm->SetRelativeRotation(FRotator(-15.0f, 0.0f, 0.0f));
GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint);
static ConstructorHelpers::FClassFinder<UAnimInstance> WARRIOR_ANIM
(TEXT("/Game/InfinityBladeWarriors/Character/Animations/WarriorAnimBlueprint.WarriorAnimBlueprint_C"));
if (WARRIOR_ANIM.Succeeded())
GetMesh()->SetAnimInstanceClass(WARRIOR_ANIM.Class);
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_CARDBOARD
(TEXT("/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Cardboard.SK_CharM_Cardboard"));
if (SK_CARDBOARD.Succeeded())
GetMesh()->SetSkeletalMesh(SK_CARDBOARD.Object);
}
입력받은 회전값을 통해 액터가 회전하게 하는 함수는 AddControllerInput
이다
각각 x축 회전을 받는 pitch, Y축 회전을 받는 yaw, z축 회전을 받는 roll이다
이제 마지막으로 GameMode에서 DefaultPawnClass를 캐릭터로 바꿔준다
*이때 캐릭터 헤더를 추가하는 것을 잊지말자