Unreal Engine에서 피치 복제 및 축 압축

발행: (2026년 3월 7일 PM 04:25 GMT+9)
7 분 소요
원문: Dev.to

죄송합니다, 번역할 텍스트를 제공해 주시겠어요? 현재는 소스 링크만 포함되어 있어 번역할 내용이 없습니다. 텍스트를 알려주시면 바로 한국어로 번역해 드리겠습니다.

Pawn 클래스

APawn 클래스에서 사용할 수 있는 함수 GetBaseAimRotation() 은 복제된 피치를 반환하며 Blueprint와 C++ 모두에서 사용할 수 있습니다.

Blueprint 단계

  1. Get Base Aim Rotation을 호출하고 그 전방 벡터를 얻습니다.
  2. 해당 방향을 월드 공간에서 Pawn의 로컬 공간으로 역변환합니다 (Pawn의 월드 변환을 사용).
  3. 결과 벡터를 분해하고 Pitch 컴포넌트를 읽습니다.

Aim offset diagram

C++ 구현

Kismet Math Library를 사용하거나 네이티브 vector/rotator 함수를 사용할 수 있습니다—두 접근 방식 모두 동일한 결과를 제공합니다.
Kismet 라이브러리를 사용할 경우 적절한 헤더를 포함하는 것을 기억하세요 (#include "Kismet/KismetMathLibrary.h").

헤더

// MyCharacter.h
class AMyCharacter : public ACharacter
{
    // ...

    /** Returns the replicated pitch value. */
    float GetReplicatedPitch() const;
};

Kismet Math Library 사용

// MyCharacter.cpp
float AMyCharacter::GetReplicatedPitch() const
{
    // World‑space aim direction from the replicated rotation
    const FVector AimDirectionWorld = UKismetMathLibrary::GetForwardVector(GetBaseAimRotation());

    // Convert to pawn‑local space
    const FVector AimDirectionLocal = UKismetMathLibrary::InverseTransformDirection(
        GetActorTransform(),
        AimDirectionWorld
    );

    // Build a rotator from the local X axis and read Pitch
    const FRotator AimRotationLocal = UKismetMathLibrary::MakeRotFromX(AimDirectionLocal);

    return AimRotationLocal.Pitch;
}

네이티브 함수 사용

float AMyCharacter::GetReplicatedPitch() const
{
    // World‑space aim direction from the replicated rotation
    const FVector AimDirectionWorld = GetBaseAimRotation().Vector();

    // Convert to pawn‑local space (no scaling)
    const FVector AimDirectionLocal = ActorToWorld().InverseTransformVectorNoScale(AimDirectionWorld);

    // Build a rotator from the local vector and read Pitch
    const FRotator AimRotationLocal = AimDirectionLocal.Rotation();

    return AimRotationLocal.Pitch;
}

두 버전 모두 소유 클라이언트에서 복제된 동일한 피치 값을 반환합니다.

내부 동작

GetBaseAimRotation()은 폰에 유효한 컨트롤러가 있는지(즉, 로컬에서 제어되는지) 여부에 따라 다르게 동작합니다. 컨트롤러가 없을 경우(시뮬레이션 프록시)에는 다른 로직을 사용합니다.

컨트롤러가 존재할 때

FVector POVLoc;
FRotator POVRot;

if (Controller != nullptr && !InFreeCam())
{
    Controller->GetPlayerViewPoint(POVLoc, POVRot);
    return POVRot;          // 플레이어의 실제 뷰 회전값을 사용
}

이 함수는 단순히 컨트롤러의 현재 뷰 회전값을 반환합니다.

컨트롤러가 없을 때(시뮬레이션 프록시)

// 폰 자체의 회전을 대체값으로 사용
POVRot = GetActorRotation();

// 피치가 0이면 복제된 RemoteViewPitch를 사용
if (FMath::IsNearlyZero(POVRot.Pitch))
{
    const UWorld* World = GetWorld();
    const UDemoNetDriver* DemoNetDriver = World ? World->GetDemoNetDriver() : nullptr;

    // 리플레이/녹화 경로 – 일반 게임플레이에서는 무시
    if (DemoNetDriver && DemoNetDriver->IsPlaying() &&
        DemoNetDriver->GetPlaybackEngineNetworkProtocolVersion() GetControlRotation().Pitch);
    }
}
  • SetRemoteViewPitch는 부동소수점 피치를 FRotator::CompressAxisToByte를 사용해 바이트(uint8)로 변환합니다.
  • 클라이언트 측에서는 GetBaseAimRotation()이 그 바이트를 FRotator::DecompressAxisFromByte를 통해 다시 전체 float 피치로 복원합니다.

요약

  • **GetBaseAimRotation()**을 사용하여 복제된 뷰 회전을 얻습니다.
  • 전방 벡터를 로컬 공간으로 변환하고 피치를 추출합니다 (Kismet Math Library 또는 네이티브 함수 중 하나 사용).
  • 내부적으로 언리얼은 서버에서 피치를 단일 바이트(RemoteViewPitch)로 압축하고 원격 클라이언트에서 압축을 해제하여 복제를 저비용·효율적으로 처리합니다.

같은 패턴을 적용해 자체 복제·압축 변수를 추가하고 PreReplication에서 처리하면 다른 축이나 사용자 정의 값을 복제할 수 있습니다.

UE4에서 Pawn 피치 복제하기

아래는 pawn 클래스 내부에서 피치 복제를 처리하는 관련 코드입니다.

1. 원격 뷰 피치 가져오기

void APawn::GetRemoteViewPitch()
{
    // Example of retrieving the remote view pitch
    float Pitch = RemoteViewPitch;               // RemoteViewPitch is a byte
    float DecompressedPitch = FRotator::DecompressAxisFromByte(Pitch);
    // Use DecompressedPitch as needed…
}

2. 원격 뷰 피치 설정하기

void APawn::SetRemoteViewPitch(float NewRemoteViewPitch)
{
    // Compress pitch to 1 byte
    RemoteViewPitch = FRotator::CompressAxisToByte(NewRemoteViewPitch);
}

참고: SetRemoteViewPitch는 네트워크 전송을 위해 float 축 값을 1바이트로 압축합니다.


사용 방법

  1. Pawn 클래스 검사 – pawn의 소스 파일을 열고 위 두 함수를 찾습니다.
  2. 흐름 이해
    • SetRemoteViewPitch는 서버(또는 소유 클라이언트)에서 피치를 압축하여 복제하기 전에 호출됩니다.
    • GetRemoteViewPitch(또는 구현한 해당 getter)는 원격 머신에서 바이트를 다시 사용 가능한 float 로 복원합니다.
  3. 내장 복제 활용 – 대부분의 경우 UE4의 기본 피치 복제를 사용하면 됩니다.
  4. 축 압축 커스터마이징 – 다른 축을 압축해야 한다면 같은 패턴을 따르세요: 복제 전 함수에서 압축하고, 복제된 값을 읽을 때 복원합니다.

마무리 생각

처음엔 세부 사항이 다소 복잡하게 느껴질 수 있지만, pawn 클래스의 이 함수들을 다시 살펴보면 이해가 확고해집니다. 대부분의 경우 엔진의 기본 피치 복제로 충분하지만, 축을 수동으로 압축하는 방법을 알면 커스텀 네트워킹 요구에 유연하게 대응할 수 있습니다.

행운을 빕니다!

0 조회
Back to Blog

관련 글

더 보기 »

Visualizer 구성 요소

Visualizer Components Visualizer components는 에디터 전용 컴포넌트로, 화면이나 HUD에 렌더링되지 않는 디버그 정보를 그립니다. 이들은 가볍고, …

Unreal Engine 3D 유체를 Flipbook으로

나는 항상 알렘빅을 사용해 피 VFX를 만들고 싶었지만, 그런 시뮬레이션은 매우 커질 수 있어 많은 게임에 실용적이지 않다. 언리얼 엔진에는 bui...

Unreal Engine에서 Move Semantics

복사 문제 전통적인 C++98 프로그래밍에서는 객체가 생성되는 두 가지 방법이 있었습니다: 처음부터 생성하는 것과 복사하는 것. ```cpp Foo; // 기본 생성자 Fooin... ```