1. 보간(Interpolation)이란?

  • 두 개의 값 사이에서 중간 값을 계산하여 자연스럽게 변화하도록 만드는 기술. 즉, 한 값에서 다른 값으로 부드럽게 이동하는 방법을 의미.
  • 언리얼 엔진에서는 다양한 보간 함수가 제공되며, 그중 FMath::FInterpTo()와 FMath::RInterpTo()를 활용하면 캐릭터의 움직임과 회전을 자연스럽게 만들 수 있다.

언리얼 엔진의 주요 보간 함수

FMath::Lerp() 선형 보간 (일정한 비율로 변화) 위치, 색상 변화
FMath::FInterpTo() 부드러운 값 변화 (속도 기반) 속도, 감속 효과
FMath::RInterpTo() 부드러운 회전 변화 회전 보간 (기체 회전)
UKismetMathLibrary::Ease() 다양한 이징 함수 제공 애니메이션 효과

2. FMath::FInterpTo()를 활용한 부드러운 이동 처리

float FMath::FInterpTo(float Current, float Target, float DeltaTime, float InterpSpeed);
  • Current: 현재 값
  • Target: 목표 값
  • DeltaTime: 프레임당 경과 시간 (GetWorld()->GetDeltaSeconds() 활용)
  • InterpSpeed: 변화 속도 (값이 클수록 빠르게 보간)
  • 결과: Current 값이 Target 값으로 InterpSpeed 속도로 점진적으로 변경됨

2-1. ASpartaPawn에서 FMath::FInterpTo() 적용 예제

void ASpartaPawn::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    UpdateRotation(DeltaTime);
    ApplyGravity(DeltaTime);
    ApplyMovement(DeltaTime);
}
  • Pawn 클래스의 Tick 함수 내부에는 CurrentVelocity(현재 속도) 벡터를 지속적으로 관리해주면서 그 값을 DeltaTime 만큼 곱하여 MoveDelta만큼 Pawn을 이동.

감속을 적용한 이동 처리 (ApplyMovement)

void ASpartaPawn::ApplyMovement(float DeltaTime)
{
    if (!CurrentVelocity.IsNearlyZero(0.01f))
    {
        FVector MoveDelta = CurrentVelocity * DeltaTime;  // Z 이동 포함
        AddActorWorldOffset(MoveDelta, true);

        CurrentVelocity.X = FMath::FInterpTo(CurrentVelocity.X, 0.0f, DeltaTime, DecelerationFactor);
        CurrentVelocity.Y = FMath::FInterpTo(CurrentVelocity.Y, 0.0f, DeltaTime, DecelerationFactor);
    }
}
  • CurrentVelocity 값을 0.0f로 점진적으로 보간하여 자연스럽게 감속되는 효과를 구현.

플레이어 이동 (MoveForward, MoveRight)

void ASpartaPawn::MoveForward(float value, float Speed)
{
    FVector ForwardVector = GetActorForwardVector();
    FVector MoveDirection = ForwardVector * value * Speed;

    CurrentVelocity.X = FMath::FInterpTo(CurrentVelocity.X, MoveDirection.X, GetWorld()->GetDeltaSeconds(), 2.0f);
    CurrentVelocity.Y = FMath::FInterpTo(CurrentVelocity.Y, MoveDirection.Y, GetWorld()->GetDeltaSeconds(), 2.0f);

    TargetRotation.Pitch = FMath::Clamp(value * -25.0f, -25.0f, 25.0f);
}
  • Pawn이 이동할 때 CurrentVelocity가 목표 속도로 부드럽게 변화하도록 FInterpTo()를 사용.

중력 적용 (ApplyGravity)

void ASpartaPawn::ApplyGravity(float DeltaTime)
{
    if (!IsOnFoot())  // 지면에 닿아 있지 않을 때 중력 적용
    {
        CurrentVelocity.Z += Gravity * DeltaTime;  // 중력 적용
    }
    else if (CurrentVelocity.Z < 0)  // 착지 시 아래로 떨어지는 중일 때만 속도 초기화
    {
        CurrentVelocity.Z = 0.0f;
    }
}

상승/하강 (Ascend/Descend)

void ASpartaPawn::Ascend(const FInputActionValue& value)
{
    if (!Controller) return;

    CurrentVelocity.Z = FMath::FInterpTo(CurrentVelocity.Z, value.Get<float>() * CurrentSpeed, GetWorld()->GetDeltaSeconds(), 2.0f);
}

void ASpartaPawn::Descend(const FInputActionValue& value)
{
    if (!Controller) return;

    CurrentVelocity.Z = FMath::FInterpTo(CurrentVelocity.Z, -value.Get<float>() * CurrentSpeed, GetWorld()->GetDeltaSeconds(), 2.0f);
}

 


3. FMath::RInterpTo()를 활용한 부드러운 회전 처리

FRotator FMath::RInterpTo(FRotator Current, FRotator Target, float DeltaTime, float InterpSpeed);
  • Current: 현재 회전 값
  • Target: 목표 회전 값
  • DeltaTime: 프레임당 경과 시간 (GetWorld()->GetDeltaSeconds() 활용)
  • InterpSpeed: 변화 속도
  • 결과: Current 값이 Target 값으로 InterpSpeed 속도로 점진적으로 변경됨

3-1. ASpartaPawn에서 FMath::RInterpTo() 적용 예제

회전 보간 적용 (UpdateRotation)

void ASpartaPawn::UpdateRotation(float DeltaTime)
{
    if (IsOnFoot())
    {
        bIsFlying = false;
        TargetRotation = FRotator(0.0f, GetActorRotation().Yaw, 0.0f);
    }
    else
    {
        bIsFlying = true;
        TargetRotation.Pitch = FMath::FInterpTo(TargetRotation.Pitch, 0.0f, DeltaTime, 3.0f);
        TargetRotation.Roll = FMath::FInterpTo(TargetRotation.Roll, 0.0f, DeltaTime, 3.0f);
    }

    SetActorRotation(FMath::RInterpTo(GetActorRotation(), TargetRotation, DeltaTime, 5.0f));
}

RInterpTo()를 사용하여 회전 값을 목표 회전 값으로 점진적으로 변화.

특히 PitchRoll 값을 FInterpTo()로 부드럽게 보간하면서도,

전체적인 회전은 RInterpTo()로 처리하여 자연스럽게 회전하도록 구현.


4. 시연 영상

 


✏️오늘도 과제를 어찌저찌 마무리했습니다.

아직 실력이 부족하여 구현해보고자 했던 것에는 실패했지만 다음 주 공부와 연계하여 이루어낼 예정입니다.


 

'TIL > C++와 UE' 카테고리의 다른 글

파티클 시스템  (0) 2025.02.11
게임 메뉴 UI 디자인  (0) 2025.02.07
비행체 움직임  (0) 2025.01.28
회전 관련 함수 및 Pawn 클래스 Look 함수  (1) 2025.01.27
충돌 검사  (0) 2025.01.24