※ 해당 기록은 Unreal 5.5.4 버전을 기준으로 작성되었습니다.
플레이어를 이동시키고 대쉬하는 기본적인 기능을 구현했다.
우선 플레이어에는 Mesh와 Delegate를 추가했다. 이 Delegate를 이용해서 플레이어가 갖고있는 컴포넌트들에서 입력을 받아 처리할 수 있을 것이다.
// AMW_Player.h에서
DECLARE_MULTICAST_DELEGATE_OneParam(FInputBindingDelegate, class UEnhancedInputComponent*);
// UInputBaseComponent.cpp에서
void UInputBaseComponent::InitializeComponent()
{
OwnerPlayer = Cast<AMW_Character>(GetOwner());
OwnerPlayer->InputBindingDelegate.AddUObject(this, &UInputBaseComponent::SetupInputBinding);
}
UInputBascComponent는 키 입력을 받는 액터 컴포넌트로, 이를 부모로 하여 UMoveComponent와 UAttackComponent 등으로 확장할 계획으로 만들었다. SetupInputBinding()을 virtual로 선언하여 자식 컴포넌트에서 구현하도록 했으므로, 자식 컴포넌트에서 구현한 함수들이 델리게이트에 모두 등록되게 된다. 이 때 델리게이트의 MULTICAST는 네트워크의 RPC와는 관계 없는 부분이므로 헷갈리지 말도록 하자. 저 부분을 SINGLE로 구현한다면 한 가지의 함수만 등록되어 나머지가 동작하지 않을 수 있다.
StateComponent를 두어 플레이어의 상태를 관찰하도록 했다. 플레이어가 특정 행동을 하면 그에 맞게 상태가 변화하고, 이를 AnimInstance에서 받아와 플레이어의 애니메이션을 바꾸는 데 사용하도록 했다.
// AMW_Player.cpp에서
bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;
bUseControllerRotationYaw = false;
GetCharacterMovement ()->bOrientRotationToMovement = true;
// 중략
SpringArmComp->SetUsingAbsoluteRotation (true); // 캐릭터가 회전해도 스프링암은 회전하지 않게
이번에 탑다운 뷰로 만들면서 다른 게임에서는 하지 않았던 설정이다. 카메라가 플레이어를 따라가는 것은 같지만, 카메라가 플레이어의 회전을 반영하지 않도록하고, 플레이어가 움직이고자 하는 방향으로 입력이 들어오면 그 방향으로 캐릭터를 회전시키는 것이다. 이런 관련된 처리를 하지 않으면 단순히 스프링암이 플레이어의 머리 위에 달려있는 TPS처럼 돌아갈 것이다.
애니메이션을 추가하기 전 우선 플레이어를 LaunchCharacter()를 이용해서 날렸다.

FSM을 이용해서 대쉬할 때 애니메이션을 재생하려고 했다. 그러나 공중에서 이동할 떄 문제가 있었다. LaunchPlayer()는 기본적으로 바닥과의 마찰에 영향을 받는다. 그래서 바닥에서 적절한 거리만큼 이동하도록 힘을 설정했어도 언덕 지형에서 바닥으로 내려올 떄, 위의 gif처럼 공중에서 보다 멀리 날아가는 현상이 있었다.

그래서 Force Root Lock 옵션을 해제하고 몽타주를 사용해서 구현하였다. 애니메이션이 자체적으로 갖는 이동 거리만큼 이동하는 방식이다.
상태 변경을 행동을 담당하는 함수에서 하고 있었다. WASD 키 입력이 들어올 때 동작하는 Move()에서 Move 상태로 전이시키는 식이다. 그러나 문제가 있었는데, 이 대쉬 몽타주가 실행되는 동안에 키 입력을 하면 해당 방향으로 이동하진 않지만 상태가 Move로 전이되는 것이다. 그래서 IsAnyMontagePlaying() 함수를 사용해서 몽타주 재생을 판단한다. 상태 전이는 액션 함수의 마지막에서 처리하게 작성해서 맨 앞줄에 체크해서 리턴하도록 구현했다.
void UMoveComponent::Move(const struct FInputActionValue& values)
{
if (animInstance->IsAnyMontagePlaying()) return;
FVector2D input = values.Get<FVector2D>();
Direction.X = input.X;
Direction.Y = input.Y;
OwnerPlayer->StateComp->SetMoveState ();
}
무기를 줍고 버리는 기능이 다음이다. 무기의 Base가 되는 클래스를 구현하고, 무기를 줍고 버리는 WeaponComp를 구현해야한다.