C++를 활용하여 언리얼 프로그래밍을 시작하며 캐릭터 이동부터 구현했습니다.
캐릭터 에셋은 Infinity Blade: Warriors를 사용하였습니다.
아쉽게도 에셋 안에 애니메이션이 없었기에 앞으로 이동은 ThirdPerson 에셋에서 가져와 사용했으며 좌우 이동과 뒤로 이동하는 동작은 믹사모의 애니메이션을 가져와 리타겟팅으로 적용하였습니다.
캐릭터 이동은 Idle/Move/Sprint 3가지를 기본으로 제작하였습니다.
이동 부분은 BindAction으로 묶었으며 Bind에서 호출된 Move함수를 사용해 캐릭터의 이동을 구현하였습니다.
void ASLPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Triggered, this, &ASLPlayerCharacter::Sprint);
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &ASLPlayerCharacter::EndSprint);
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ASLPlayerCharacter::Move);
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASLPlayerCharacter::Look);
}
void ASLPlayerCharacter::Move(const FInputActionValue& Value)
{
FVector2D MovementVector = Value.Get<FVector2D>();
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(ForwardDirection, MovementVector.X);
AddMovementInput(RightDirection, MovementVector.Y);
}
달리기 부분은 간단하게 Shift 클릭 시 속도를 변하게 만들어주는 것으로 구현하였습니다.
void ASLPlayerCharacter::Sprint()
{
GetCharacterMovement()->MaxWalkSpeed = 600.f;
}
void ASLPlayerCharacter::EndSprint()
{
GetCharacterMovement()->MaxWalkSpeed = 300.f;
}
다음으로는 AnimInstance에서 애니메이션 블루프린트에 상속될 코드를 작성하였습니다.
블랜드 스페이스에서 GroundSpeed와 Direction을 사용해야 함으로 GroundSpeed는 Velocity의 크기를 가져왔고 Direction은 CalculateDirection함수를 사용하여 각도를 구해주었습니다.
애니메이션 블루프린트에서 사용할 변수인 IsIdle, IsFalling, IsJumping들도 구현해주었습니다.
void USLCharacterAnimInstance::NativeInitializeAnimation()
{
Super::NativeInitializeAnimation();
Owner = Cast<ACharacter>(GetOwningActor());
if (Owner)
{
Movement = Owner->GetCharacterMovement();
}
}
void USLCharacterAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
// Speed & Direction
APawn* Pawn = TryGetPawnOwner();
if (!::IsValid(Pawn)) return;
GroundSpeed = Pawn->GetVelocity().Size();
Direction = CalculateDirection(Pawn->GetVelocity(), Pawn->GetActorRotation());
// Bool
if (Movement)
{
bIsIdle = GroundSpeed < MovingThreshould;
bIsFalling = Movement->IsFalling();
bIsJumping = bIsFalling & (Velocity.Z > JumpingThreshould);
}
}