본문 바로가기
언리얼(Unreal)/네트워크

25.03.19 Prediction and Reconciliation

by alwaysyoung2 2025. 3. 19.
728x90
반응형

Client-Side Prediction (클라이언트 측 예측)

Client-Side Prediction은 멀티플레이어 게임에서 네트워크 지연(렉)을 최소화하고, 플레이어의 조작감을 부드럽게 만드는 핵심 기술입니다. 이 기술은 클라이언트가 서버의 응답을 기다리지 않고, 먼저 자신의 캐릭터를 움직인 후 나중에 서버의 결과를 받아 수정하는 방식으로 동작합니다.


Client-Side Prediction의 동작 원리

  1. 클라이언트 입력 & 로컬 이동:
    • 플레이어가 이동 키를 누르면, 클라이언트는 즉시 캐릭터를 움직입니다. (예측 동작)
    • 동시에 서버에게 "이 방향으로 이 시간에 움직였다"는 정보를 전송합니다.
  2. 서버 시뮬레이션:
    • 서버는 클라이언트의 이동 요청을 받아 검증합니다. (예: 캐릭터가 움직일 수 있는 상태인지 확인)
    • 서버는 클라이언트의 입력대로 캐릭터를 움직이고, 새로운 위치를 계산합니다.
  3. 클라이언트에 서버 결과 적용 (보정):
    • 서버는 계산된 새로운 위치를 클라이언트에게 전송합니다.
    • 클라이언트는 서버의 결과와 자신의 예측을 비교합니다.
    • 차이가 있다면, 클라이언트는 서버의 위치로 캐릭터를 보정합니다.
  4. Smoothing (스무딩):
    • 보정 과정에서 발생할 수 있는 불연속적인 움직임을 부드럽게 만듭니다.
    • 예: 캐릭터가 순간이동하지 않고, 자연스럽게 이동합니다.
  5. 다른 플레이어 캐릭터의 Movement Smoothing:
    • 다른 플레이어의 캐릭터도 부드럽게 보이도록 합니다.
    • 클라이언트는 다른 플레이어의 위치를 일정 간격으로 업데이트 받고, 그 사이를 보간(Interpolation)하여 부드럽게 표시합니다.

Client-Side Prediction의 장점

  1. 즉각적인 조작감: 플레이어의 입력이 즉시 반영되어 부드러운 게임 플레이를 제공합니다.
  2. 네트워크 지연 최소화: 서버의 응답을 기다리지 않아도 되므로 렉이 줄어듭니다.
  3. 부드러운 움직임: Smoothing 기술로 인해 캐릭터의 움직임이 자연스럽게 보입니다.

Client-Side Prediction의 단점

  1. 예측 오류: 클라이언트의 예측과 서버의 결과가 다를 수 있습니다.
    • 예: 클라이언트에서는 문을 통과했지만, 서버에서는 문에 막혀서 되돌아오는 경우.
  2. 복잡성: 예측, 보정, Smoothing을 구현하려면 추가적인 로직이 필요합니다.

언리얼 엔진에서의 Client-Side Prediction

  • 언리얼 엔진의 CharacterMovementComponent는 Client-Side Prediction을 자동으로 처리합니다.
  • 개발자는 이 컴포넌트를 사용해 쉽게 부드러운 캐릭터 이동을 구현할 수 있습니다.
  • 단, 커스터마이징한 이동 로직을 추가할 때는 예측-보정 과정을 고려해야 합니다.

Client-Side Prediction의 중요성

  • 빠른 멀티플레이 게임을 만들 때 필수적인 기술입니다.
  • 플레이어 경험을 향상시키고, 네트워크 지연을 최소화합니다.
  • 언리얼 엔진이 많은 부분을 자동으로 처리하지만, 원리를 이해하고 커스터마이징할 수 있어야 고급 네트워킹을 다룰 수 있습니다.

쉽게 정리하면!

  • Client-Side Prediction은 클라이언트가 서버의 응답을 기다리지 않고 먼저 움직이는 기술입니다.
  • 예측 → 서버 검증 → 보정 → Smoothing 과정을 통해 부드러운 게임 플레이를 제공합니다.
  • 언리얼 엔진의 CharacterMovementComponent는 이 기능을 자동으로 지원합니다.

Lag Compensation and Hit Detection

**랙 컴펜세이션(Lag Compensation)**은 멀티플레이어 게임에서 네트워크 지연(렉)으로 인해 발생하는 불공정한 상황을 해결하기 위한 기술입니다. 쉽게 말해, "플레이어가 본 화면대로 공격이 적용되도록" 서버가 과거 상태를 재현하여 판정하는 방법입니다


왜 필요할까요?

  • 예시:
    • 플레이어 A가 B를 향해 총을 쐈습니다. A의 화면에서는 명중했지만, 서버는 B가 이미 이동한 뒤라 "빗나감"으로 처리할 수 있습니다.
    • 이럴 때 A는 **"내 화면에선 맞았는데!"**라며 불만을 느낍니다. 특히 핑(ping)이 높은 플레이어는 더 자주 이런 상황에 부딪힙니다.

두 가지 해결 방법

1️⃣ 클라이언트 권한 히트 감지 (Client-Authoritative Hit Detection)

  • 방식: 클라이언트가 **"맞췄다"**고 서버에 알리면, 서버는 이를 그대로 믿고 데미지를 적용합니다.
  • 장점: 구현이 쉽고 즉각적인 피드백을 제공합니다.
  • 단점:
    • 핑이 높은 플레이어가 과거의 상대 위치를 보고 공격하면, 서버 측 실제 위치와 달라 부정확할 수 있습니다.
    • 해킹이나 조작에 취약할 수 있습니다.

💡 예시:
핑 200ms인 A가 B를 쐈을 때, B는 이미 엄폐물 뒤로 숨었지만, A의 화면에선 B가 아직 그 자리에 있어 서버가 "맞음"으로 처리하면 불공평해집니다.


2️⃣ 서버 측 랙 컴펜세이션 (Server-Side Lag Compensation)

  • 방식:
    1. 서버는 모든 플레이어의 과거 위치를 기록합니다 (예: 최근 0.2초 동안의 위치).
    2. 플레이어가 공격할 때 **"발사 시간"**을 서버에 전송합니다.
    3. 서버는 해당 시간으로 되돌아가 그 순간의 위치로 히트 판정을 합니다.
  • 장점:
    • 클라이언트가 본 화면과 서버 판정이 일치해 공정합니다.
    • 고핑 상황에서도 공평한 게임 플레이가 가능합니다.
  • 단점:
    • 서버 부하 증가 (과거 데이터 저장 및 계산 필요).
    • 구현 복잡도가 높습니다.

💡 예시:
A가 총을 쏜 시간을 서버에 전달하면, 서버는 그 시간대의 B 위치를 복원해 **"과거의 B"**를 맞췄는지 판단합니다.


언리얼 엔진에서의 구현

  • 언리얼은 기본적으로 Client-Authoritative Hit Detection을 사용합니다.
    • ShooterGame 예제처럼 클라이언트가 히트 판정을 주도합니다.
  • Server-Side Lag Compensation을 구현하려면 개발자가 직접 추가해야 합니다.
    • 필요한 작업:
      1. 플레이어 위치 기록 시스템 구축.
      2. 공격 이벤트에 타임스탬프 추가.
      3. 서버에서 과거 위치 복원 및 충돌 검증 로직 작성.

어떤 방법을 선택할까요?

  • 클라이언트 권한 방식:
    • 빠른 개발이 필요할 때, 캐주얼 게임에 적합.
  • 서버 측 랙 컴펜세이션:
    • FPS, 경쟁적 게임처럼 정확한 판정이 critical할 때 필수.

결론

  • 랙 컴펜세이션은 네트워크 지연을 보상해 플레이어 경험을 공정하게 만드는 기술입니다.
  • 장점: 높은 핑에서도 공격이 "내가 본 대로" 적용됩니다.
  • 주의점: 서버 성능과 구현 복잡도를 고려해야 합니다.

 

**Server Reconciliation (서버 보정)**은 멀티플레이어 게임에서 클라이언트의 예측과 서버의 실제 상태가 달라질 때, 클라이언트가 서버의 상태에 맞춰 자신을 수정하는 과정입니다. 이는 플레이어의 조작감을 유지하면서도 서버의 권한 있는 데이터와 동기화하기 위한 핵심 기술입니다. 


Server Reconciliation의 동작 원리

1️⃣ 서버 상태 수용

  • 문제 상황: 클라이언트가 예측한 움직임과 서버의 실제 결과가 다를 수 있습니다.
    • 예: 클라이언트는 "A 지점으로 이동했다"고 생각했지만, 서버는 "B 지점에 있다"고 알려줍니다.
  • 해결 방법:
    • 서버가 보낸 최신 상태(위치, 속도 등)를 클라이언트가 무조건 수용합니다.
    • 예: 서버가 "시간 T에 너의 위치는 X야"라고 알리면, 클라이언트는 즉시 위치 X로 이동합니다.

2️⃣ 보류 중인 입력 재적용

  • 문제 상황: 서버의 응답을 기다리는 동안 클라이언트가 추가 입력을 실행했을 수 있습니다.
    • 예: 서버가 "시간 T까지 처리 완료"했지만, 클라이언트는 T 이후에 입력 #11, #12를 더 실행했습니다.
  • 해결 방법:
    • 클라이언트는 서버의 상태를 기반으로 미처리된 입력을 다시 실행합니다.
    • 예: 위치 X에서 입력 #11, #12를 다시 적용해 최신 상태를 계산합니다.

왜 필요할까요?

  • 목적: 플레이어의 즉각적인 조작감을 유지하면서, 서버와의 정확한 동기화를 달성합니다.
    • 클라이언트는 미리 움직임을 예측하지만, 서버의 최종 결정을 존중해야 합니다.
    • 예: 서버가 "문에 막혀 움직일 수 없다"고 판단하면, 클라이언트는 문 앞으로 되돌아갑니다.

예시로 이해하기

  1. 이동 보정:
    • 클라이언트: "내 캐릭터가 점프했다!" (예측 실행).
    • 서버: "점프 조건이 안 되어 점프 실패" (보정 명령).
    • 결과: 클라이언트는 점프 애니메이션을 취소하고 원래 위치로 복귀합니다.
  2. 스킬 사용 보정:
    • 클라이언트: "마나가 충분하니 스킬 발동!" (예측 실행).
    • 서버: "마나가 부족해 스킬 불가" (보정 명령).
    • 결과: 클라이언트는 스킬 이펙트를 중단하고 마나를 복구합니다.

Unreal Engine에서의 구현

  • 기본 지원: CharacterMovementComponent는 이동 관련 보정을 자동으로 처리합니다.
    • 서버의 위치/속도 업데이트 → 클라이언트가 즉시 보정 → 미처리 입력 재적용.
  • 커스터마이징: 새로운 기능(벽 타기, 차량 운전 등)을 추가할 때는 개발자가 직접 보정 로직을 구현해야 합니다.
    • Gameplay Ability System (GAS): 스킬 예측과 보정을 위해 Prediction Key를 사용해 서버와 클라이언트를 동기화합니다.

중요한 원칙

  1. 부드러운 보정: 순간이동처럼 보이지 않게 **스무딩(Smoothing)**을 적용합니다.
    • 예: 서버 위치로 천천히 이동하거나, 미세한 오차는 무시합니다.
  2. 최소한의 보정: 예측 정확도를 높여 보정 발생을 줄입니다.
    • 예: 물리 계산을 클라이언트와 서버가 동일하게 유지합니다.

왜 신경 써야 할까요?

  • 플레이어 경험: 자주 튕기거나 되돌아가는 현상은 불편함을 유발합니다.
  • 공정성: 서버의 결정을 존중하면서도 클라이언트의 예측을 자연스럽게 반영해야 합니다.

결론

  • Server Reconciliation은 **"예측 → 서버 검증 → 보정"**의 사이클을 통해 부드러운 멀티플레이어 경험을 제공합니다.
  • 언리얼 엔진은 기본 시스템을 지원하지만, 복잡한 기능을 추가할 때는 개발자의 이해가 필수적입니다.
  • 핵심은 **"플레이어가 눈치채지 못할 정도로 자연스럽게 보정하는 것"**입니다
728x90
반응형