멀티-플레이어 게임 서버와 레이턴시 보상 테크닉

scalalang2
취미로 논문 읽는 그룹
26 min readOct 16, 2023

--

멀티-플레이어 게임 서버는 높은 레이턴시 환경에서 일관성과 반응성이 떨어지기 마련인데 이러한 부정적 경험을 숨기기 위한 여러 보상 테크닉들이 존재한다. 오늘은 레이턴시 보상 연관 논문 80여개를 정리하고 분류 체계를 만든 서베이 논문 한 편을 소개한다. 이 논문은 레이턴시 보상 분야의 기존 연구들의 성과와 발전 방향을 정리했다. 이런 잘 쓰여진 서베이 논문 한 편 딱 읽어두면, 나중에 다른 논문을 읽을 때 도움이 된다.

이 글이 게임업계의 서버 프로그래머 분들과 게임업계를 꿈꾸는 학생분들 그리고 게임에 관심있는 다른 분야의 서버 프로그래머들에게 흥미로운 내용이 되길 기대한다.

A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games — ACM Survey 2022에 기고된 논문으로 저자인 SHENGMEI LIU는 우스터 폴리테크닉 대학에서 박사과정을 마치고 현재 구글의 소프트웨어 엔지니어로 재직중이다.

(옮긴이) 국내 어느 한 게임회사에서 밥만 축내는 서버 프로그래머이다.

Table of Contents

  • 게임 서버 네트워크와 동기화
  • 레이턴시 보상 (Latency Compensation)
  • 피드백 (Feedback)
  • 예측 (Prediction)
  • 시간 조작 (Time Manipulation)
  • 월드 조정 (World Adjustment)
  • 마무리

게임 서버 네트워크와 동기화

게임 네트워크의 토폴로지는 크게 4가지로 구분할 수 있다.

  • Peer-to-Peer : 서버 없이 플레이어들이 직접 통신하는 구조이다. 게임 이외에 별도 서버가 필요없어서 수업 시간에 선생님이 인터넷을 끊어도 스타크래프트를 할 수 있다는 장점이 있다. 하지만 게임의 전체 상태를 동기화 하고 입력값을 검증하는 서버가 없어서 치팅(e.g. 핵)에 취약하고 성능이 낮은 플에이어에게 전체 플레이 성능이 바운드된다.
  • Dedicated Game Server (DGS) : 데디케이트 서버란 게임 로직 전체 혹은 일부가 원격지 전담 서버로 호스팅 되고 클라이언트는 데디케이트 서버에 붙어서 게임 한 판을 진행한다. 클라이언트-서버 구조로 통신하게 된다. 배틀그라운드에서는 매칭이 완료되면 수십명의 사람이 외딴 섬에 낙하산을 타고 내려와 생존 게임이 시작되는데 이 때 데디케이트 서버가 이번 판의 게임 상태 동기화를 책임진다. 매 판마다 플레이를 책임지는 서버가 분리되어 있어서 한 서버의 문제가 다른 게임을 하고 있는 플레이어에게 전파되지 않는다. 쾌적한 게임 플레이를 위해서는 메모리, CPU, 네트워크 대역폭 이 세가지 요소를 모두 풍부하게 제공해야한다. 그래서 보통 데디케이트 서버를 제공해야하는 온라인 게임 서비스들은 서버 비용이 억 소리나게 나간다. 에픽게임즈의 포트나이트는 3400만명 동접을 수용하기 위해 수천대의 AWS c4.8xlarge 인스턴스를 운영하고 있다고 밝힌 바 있다. 대략 2500대를 운영하고 있다고 가정하면 데디케이트 서버 혼자서만 한달에 30억씩 비용이 필요하다.
[Fig 1. 게임:배틀그라운드 — 게임 시작과 함께 플레이어들이 낙하산을 타고 포인트로 하강하는 모습]
  • Client Server Model : 클라이언트-서버 모델로 서버 하나가 동기화를 책임지는 모델을 말한다. 데디케이트 서버랑 구분을 둔 이유는 MMORPG처럼 판수 개념이 없는 실시간 온라인 게임에서 필요한 서버 형태랑은 개념이 미묘하게 다르다고 생각했기 때문이다.
  • Listen Server (Client-Hosted Model) : 클라이언트-서버 모델이지만 게임 플레이어 중 하나를 호스트로 선정해서 해당 유저가 서버 역할까지 책임지면서 플레이 하는 방식을 말한다. 개발자 입장에서는 서버 유지비를 아낄 수 있다. 경쟁이 중요한 요소가 아니라면 이 모델을 고려해볼 수 있다.

보통은 네 가지 모델 중에서 한 가지 정도를 채택하지만, 만드는 게임의 요구사항에 따라 적절히 혼합해서 사용할 수 있다. 넥슨게임즈는 언리얼 엔진에서 Dedicated Server와 Listen Server를 혼합해서 사용한 SPICA를 NDC에서 두 번의 발표를 통해 소개헀다.

게임 서버 동기화 (Synchronization)

멀티-플레이어 게임에서 나와 내 친구 혹은 떨어져 있는 누군가와 같은 게임을 플레이 하고 있다는 걸 보여주려면 매 순간 게임 상태가 동기화 되어야 한다. FPS 게임에서 나는 엄폐물로 이동해서 숨어있는데 동기화 시간 차이로 적한테는 신체 부위가 노출된 상태라면 원활한 게임 자체가 불가능하다. 게임 업계에서는 이런 상태 동기화 이슈를 흔히 NETCODE 라고 부른다.

게임 서버는 NETCODE 이슈를 줄이기 위해 적절한 동기화 전략을 채택해야 한다. 넥슨 개발자 컨퍼런스의 발표에서 발췌한 내용을 토대로 게임 서버의 동기화란 무엇인지 어떤 방식으로 동작하는지 가장 기본적인 원형을 소개한다. 다음 장에서부터 본격적으로 논문 내용을 다루면서 레이턴시로 인한 동기화 이슈를 해결하는 방법에 대해 다루려고한다.

① Lock-Step Protocol

Lock-Step 방식은 가장 단순한 게임 동기화 모델이면서 동시에 안티 치팅 프로토콜이다. P2P 네트워크에서는 상대방이 이번 프레임에 어떤 행동을 했는지 먼저 보고 나의 행동을 결정하면서 치팅할 수 있는데 이를 lock-ahead cheating 이라고 부른다. 주식 시장에서 선행 매매(Front-Running)와 비슷한 원리라고 생각하면 된다.

Lock-step Protocol에서는 각 행위에 대한 커미트먼트(e.g. hash)를 먼저 전파하고 이를 동의하면 모든 플레이어 행위가 공개되고 동기화를 진행한다. lock-ahead cheating 문제의 부분적인 해법을 제공하지만 가장 레이턴시가 느린 플레이어에게 게임의 품질이 바운드 되며 게임에 참여할 수 있는 인원이 제한된다. 턴제 게임에서는 체감하기 어렵지만 높은 반응성이 요구되는 FPS 게임에서 Lock-step으로 구현하면 플레이 경험이 감소할 것이다.

Lock-step protocol은 설명하는 자료마다 정의하는 방식이 조금 다르다. 안티치팅 기능만 버리고 각 라운드별로 동기식으로 동기화 한다는 의미로 Lock-step synchronization 이라는 용어를 따로 분리해서 설명하기도 한다(출처: 라인 기술 블로그). 일단 이 글에서는 위키백과에 등재된 단어를 더 근본으로 쳐서 소개했다. 동일한 입력값에 대해 상태 전이가 결정적으로 동작하기 때문에 Deterministic Lock-step 이라고 부르기도 한다.

[Fig 3. Lock-Step Protocol의 동기화 모델]

대표적인 예시로 국민 민속놀이 스타크래프트가 있는데 4:4 빠른 무한의 후반부가 되면 1000개 이상의 오브젝트 상태를 전송할 수 있는 대역폭이 필요하다. 스타크래프트가 탄생한 시점과 그 당시 컴퓨터의 사양을 생각해보면 아마 클라이언트 상태 커미트머트만 매 라운드마다 합의하는 방식을 이용했을 것이다.

[Fig 4. Lock-step 방식의 동기화 모델에서 플레이어의 지연이 전체 플레이어의 블럭킹으로 이어진다.]

Lock-step 방식으로 동기화 하는 모델에서는 플레이어 한명의 지연이 모든 플레이어에게 영향을 준다. 스타크래프트에선 한 명의 네트워크 이슈가 발생하면 45초 동안 기다렸다가 플레이어의 추방 투표가 진행됟다.

② 서버 허가형 모델(Server Authoritative)

Lock-step 방식은 클라이언트가 직접 이벤트를 받아서 직접 렌더링 하는 방식인 반면, 서버 허가형 모델은 서버가 게임 렌더링에 필요한 월드 상태 로직을 직접 가지고 있으면서 클라이언트에게 사물의 위치나 상태 등을 방송하는 방식을 말한다.

[Fig 5. 서버 허가형 모델(Server Authoritative)]

서버가 먼저 게임의 상태를 전이한 뒤, 클라이언트가 서버의 상태를 뒤따라가면서 렌더링 하는 방식이다. 클라이언트는 항상 서버의 과거 상태를 뒤늦게 반영하게 된다. 서버는 클라이언트의 입력을 받을 때 입력값에 대한 검증 및 상태를 업데이트 한다. 만약 클라이언트가 갑자기 순간이동 한다거나 게임 내에서 일어날 수 없는 행위를 하면 서버에서 해당 이벤트를 거부할 수 있다. 아마 이런 특징 때문에 서버 허가형 모델이라고 불리는 듯 하다.

Tick Rate는 게임 서버의 방송 주기이다. 만약 16.66ms 주기로 클라이언트로 방송한다면 게임 서버는 1초에 60프레임을 계산하는 상황이고 이때 Tick rate는 헤르츠(Hz) 단위로 표현해서 60Hz 라고 부른다.

[Fig 6. Unity | Ticks and update rates]

Tick Rate는 게임의 종류마다 다르게 선택할 수 있다. FPS 장르를 생각해보자. Tick Rate 10Hz 게임은 1분에 약 600 프레임을 계산한다. 만약 1분에 750발을 발사할 수 있는 총기가 있다고 했을 때, 어떤 특정 한 프레임에서 플레이어는 상태가 반영되는 시점에 이상하게 다른 프레임보다 데미지가 더 높게 발생하는 현상을 겪게 된다. 플레이어의 행위가 턴마다 제한되는 턴제 게임에서는 Tick Rate를 여유롭게 선택할 수 있다.

넥슨의 FPS 신작 베일드 엑스퍼트(VX)는 경쟁전에 한해 100Hz라는 높은 틱레이트를 제공하고 이미 성공해 버려서 돈을 많이 버는 라이엇 게임즈의 발로란트는 128Hz를 제공한다. 컴퓨터의 그래픽 카드나 모니터의 주사율이 낮으면 이런 성능 좋은 서버의 혜택을 제대로 못받을 수 있다. 친구들과 만남의 장인 PC방을 가면 높은 주사율의 모니터를 제공하는 FPS전용 좌석이 따로 마련되어 있는 걸 볼 수 있다.

이번 장에서는 게임 서버의 네트워크 종류와 동기화의 가장 기본적인 두 가지 모델에 대해서 다루었다. 다음 장 부터 본격적으로 레이턴시가 게임에 미치는 영향과 함께 이를 숨길 수 있는 레이턴시 보상 기술들에 대해 알아보자.

레이턴시 보상 (Latency Compensation)

[Fig 7. 출처 : 논문에서 발췌한 반응성과 일관성에 대한 그림]

레이턴시는 게임 플레이의 반응성(Responsiveness)일관성(Consistency)에 영향을 미친다. 그림의 (a) 예시에서는 플레이어가 입력을 전송하고 서버가 상태를 업데이트 하고 전달하는데 나의 행위와 상태 전이 사이에 시간이 존재한다. 이 시간이 클 수록 반응성은 떨어지고 프레임 드랍이 발생한다. (b예시는 일관성의 문제를 보여준다. 클라이언트 A는 이미 월드 상태를 업데이트 했는데 클라이언트 B로 가는 통신이 지연이 발생하면 서로 바라보고 있는 대상의 위치가 달라지게 된다. 플레이어의 위치가 중요한 경쟁 게임에서는 이런 작은 불일치가 플레이 경험에 크게 영향을 미친다.

[Fig 8. 반응성과 일관성의 트레이드-오프 관계]

일관성과 반응성은 일종의 트레이드-오프 관계가 형성된다. 그림에서 좌표 (0,0)인 원점이 가장 좋은 상태인데 네트워크 지연이 존재하는 한 사실상 도달할 수 없는 경지이다. 여기서 일관성을 지키려고 하면 반응성을 훼손하게 되고 반응성을 지키고자 하면 일관성이 훼손된다.

두 특징 사이의 의사결정은 게임 플레이의 종류에 따라 다르다. 광활한 맵에서 캐릭터를 다른 지역으로 이동하는 행위는 일관성은 조금 부족해도 되지만 트랙위를 달리는 레이싱 게임에서는 높은 일관성이 필요하다. FPS게임에서도 넓은 범위를 타격하는 무기와 좁은 범위를 정밀 타격하는 무기 사이에서 필요한 일관성 수준이 다를 수 있다. (e.g. 오버워치의 윈스턴과 위도우메이커)

레이턴시 보상 (Latency Compensation)은 레이턴시에 따른 부정적 경험을 줄이기 위해 사용자의 입력이나 게임의 상태값을 조정하는 테크닉을 표현하는 단어이다. 이 논문은 총 80여개의 관련 연구를 조사하고 4가지 그룹의 11개의 테크닉으로 레이턴시 보상을 분류화/체계화 했다.

[Fig 9. Latency Compensation Techniques]
[Fig 10. 논문에서 각 분류화된 용어마다 참고한 논문들을 표로 나타낸 것이다.]

[Fig 9] 에서 초록색으로 칠해진 영역은 클라이언트 코드에서 적용할 수 있는 테크닉을 의미하고 파랑색은 서버에서 사용하는 테크닉을 나머지는 클라이언트/서버 모두에 적용할 수 있는 기법들을 표현한다. 이 포스팅의 나머지 단락에서는 이 분류의 큰 그룹인 피드백, 예측, 시간 조작, 월드 조정에 대해 다루고자 한다.

논문에서는 각 기법마다 플레이어가 얼마나 태스크를 잘 수행하는지, 게임 플레이의 만족도는 어떻게 변화하였는지 등 영향을 평가한 관련 연구를 포함하고 있다. 이 포스팅에서는 각 테크닉이 무엇인지에 대해서만 소개한다.

피드백 (Feedback)

피드백이란 실제 게임 상태를 변경하지 않고 시각적, 음향적 정보를 이용하면서 레이턴시를 느끼지 않도록 하는 방법이다.

레이턴시 은폐(Latency Concealment)
플레이어의 입력에 변경되지 않는 게임 상태를 은폐하는 방법이다. 예를 들면, 레이싱 게임에서 부스터를 쓰면 차량이 빠르게 앞으로 이동해야 하는데 서버가 이동 처리를 하기 전에 먼저 부스터 이펙트나 소리부터 먼저 보여줌으로써 레이턴시에 대한 인식을 숨긴다. FPS에서는 총알이 발사되는 것을 서버가 패킷을 받아보기 이전에 클라이언트에게 먼저 반동을 보여줄 수 있다.

[Fig 11. 레이턴시 은폐 — Latency Concealment]

위 그림은 이를 잘 표현해주는데 플레이어 입력 N시점에 시각적 효과를 먼저 보여주고 t2 시간에서 실제 게임 상태가 반영된다. 그리고 이미지 워핑(image warping) 또한 레이턴시 은폐 카테고리에 속한다. 이미지 워핑은 이미지 프로세싱의 한 분야로 원본 이미지를 왜곡시키는 기술이다.

[Fig 12. 좌-원본이미지, 우-워핑된 이미지]

NVIDA의 2020년 논문에서는 이미지 워핑을 통해 FPS게임에서 에임 시점을 자연스럽게 변형하는 방법을 소개한다. 렌더링이 아니라 굳이 이미지 워핑인 이유는 클라우드 게임을 대상으로 작성된 논문이기 때문이다.

레이턴시 노출 (Latency Exposure)
레이턴시 노출은 사용자에게 클라이언트-서버간 레이턴시를 시각정 정보로 제공하는 것을 말한다. 게임의 상하단 모서리를 잘 보면 라운드-트립 시간을 작게 표기해주는 경우가 있다.

[Fig 14. 레이턴시 노출]

이게 뭔가 싶겠지만 놀랍게도 몇몇 연구는 레이턴시를 노출시켜주는게 하나의 좋은 전략이 될 수 있다고 소개한다. 대표적으로 이 연구에서는 테니스 게임을 할 때 플레이어에게 지연 시간을 노출 시키면 유저가 스스로 볼의 궤적을 예측하면서 대처하기 때문에 더 나은 플레이가 가능하다고도 보고한다.

예측 (Prediction)

서버 허가형 모델에서는 서버가 플레이어의 행위를 인가해주고 렌더링된 결과를 클라이언트에게 보고한다. 예측은 서버에게 결과를 받기 전에 클라이언트가 미리 예측해서 먼저 렌더링 하고 나중에 서버의 결과를 받아서 보정하는 방식이다. 예측은 실제 게임 업계에서 정말 자주 쓰이는 기법이고 넥슨 개발자 컨퍼런스(NDC)에서도 자주 소개되었다.

예측은 반응성을 높여서 플레이 경험에 긍정적인 영향을 주기도 하지만 유저간 일관성을 깨뜨려 문제가 되기도 한다. 만약 플레이어가 이동을 했는데 서버가 입력을 거부하거나 또는 레이턴시가 너무 큰 상황에서 클라이언트의 세계와 서버의 세계가 너무 다르다면 플레이어의 위치가 강제로 이동되거나 나도 모르게 피격 판정을 받는 등 불쾌한 경험을 주게 된다.

셀프 예측(Self-prediction)
게임은 그 자체로 게임 엔진 위에서 동작하기 때문에 클라이언트에서 예측기법을 적용하기 굉장히 용이한다. 플레이어의 행위가 입력되면 클라이언트가 먼저 진행하고 서버에게 허가를 구한다. 왠만하면 서버가 허락해주겠지 라는 가정이 있다면 아주 좋은 방법이다. 서버가 너무 자주 플레이어의 입력을 거부하면 셀프-예측은 무용지물이 될 것이다. 이런 특징 때문에 몇몇은 낙관적 동시성(Optimistic Concurrency)에 비유해서 설명하기도 한다.

[Fig 15. Self-prediction]

[Fig 15]를 보자, t0에서 플레이어의 입력을 받아서 클라이언트에서 먼저 오브젝트를 이동시킨다. 이후 서버로 전송해서 반영된 월드 상태를 받았을 때는 나의 입력이 허가를 받거나, 허가를 거부하거나 둘 중 하나의 상태로 결정된다. 서버의 상태와 나의 상태가 동일하면 새로운 위치가 컨펌되지만 입력이 거부되었다면 서버의 상태로 클라이언트의 상태가 롤백 처리된다.

입력이 거부된 상태가 아니어도 클라이언트와 서버 사이의 지연이 크면 러버밴딩(rubber-banding)문제가 발생할 수 있는데, 클라이언트의 화면이 항상 게임 서버 상태보다 미래 시점이기 때문에 서버의 상태를 너무 늦게 전달받으면 서버의 과거 상태로 보정되면서 [Fig 16] 처럼 보여진다.

[Fig 16. Rubber banding]

완벽한 해결방법은 아니지만, 그래도 여러 연구결과에 따르면 100ms-150ms 사이의 레이턴시 환경에서 유저가 게임 내 태스크를 수행하는데 있어, 셀프-예측 기법을 적용하면 15~20%의 퍼포먼스 향상이 있다고 한다.

보간법(Interpolation)
정보가 적은 상황에서 렌더링 할때 좀 더 자연스럽게 보정하는 방법으로 게임 서버로부터 받은 상태 정보와 바로 이전까지 가지고 있던 상태 정보의 중간 상태를 예측해서 렌더링 하는데 끼워넣는 방식이다.

[Fig 17. Interpolation]

서버의 방송주기(Hz)보다 클라이언트의 초당 프레임이 더 많을 때 자연스럽게 표현하기 위해 사용할 수 있다. 예를 들어 서버의 방송주기가 30Hz, 클라이언트의 렌더링 주기가 60Hz인 상황이라면 부족한 정보를 채워서 렌더링 해야한다. 이 때 쓰이는 예측을 보간법(Interpolation)이라고 부른다. 아래 영상을 보면 그 효과를 볼 수 있다.

[Fig 18. Frame Rate Interpolation]

추론 (Extrapolation)
추론은 신호가 오지 않는 동안의 행동을 플레이어가 추측해서 상태를 갱신하는 알고리즘이다. [Fig 19] 에서 t0에서 t1로 오브젝트의 상태가 업데이트 되었다면 t2에서 서버로부터 응답을 받지 못했을 때, 클라이언트가 새로운 포지션을 추론해서 렌더링 할 수 있다.

[Fig 19. Extrapolation]

추론은 레이턴시 보상 테크닉 중에서도 오랜시간 동안 많이 연구된 분야여서 게임 업계에서 정말 자주 쓰이는 방식이다. 업계에서는 데드 레커닝(dead-reckoning) 이라는 이름으로 널리 알려져 있다. 데드 레커닝은 오브젝트의 위치, 속도, 중력 가속도 등의 물리값으로 다음 상태를 예측하는 방법이다.

만약 속도(velocity)값을 알고 있다면 렌더링 시간 차이를 곱해서 현재 위치를 계산할 수 있다. 다른 예로 중력가속도 처럼 상수값의 가속도가 주어지는 환경에서는 가속도 값을 이용해서 현재 위치를 계산할 수 있다.

[Fig 20. 속도를 이용한 위치 추론]
[Fig 21. 가속도가 주어진 환경에서 위치 추론]

일반적으로 자유낙하 처럼 관성이 많이 적용되는 환경의 물체가 예측이 정확하고, 관성이 적고 플레이어의 개입이 많은 물체일수록 예측이 어려워 진다. 데드레커닝의 정보 처리에 쓰이는 건 게임과 상황마다 난이도가 달라진다.

[Fig 22. 추론 정보의 단순함/복잡성 정도]

물리법칙이 적용되서 간단하게 연산할 수있는건 정확도가 매우 높고 알고리즘이 단순하다. 만약, 오브젝트가 목적지 까지 이동하는 경로에 장애물이나 존재하거나 다른 환경적 요소가 존재하면 더 많은 프로세싱이 필요하고 AI가 컨트롤 하는 NPC의 위치를 잡는다거나 머신러닝이 들어가면 추론에 쓰이는 연산이 복잡해지는 특징을 가지고 있다. 어떤 연구에서는 주변 환경과 플레이어가 관심을 가질만한 주변 사물을 가지고 행위를 예측하는 방법을 제안하기도 했다.

[Fig 23. 배틀그라운드의 보급상자, 죽어도 봐야지]

일반적으로 데드레커닝은 (a) 반응성을 높이고, (b) 클라이언트의 추론만 정확하다면 네트워크 통신량을 줄이는데 쓰이고 있다.

투기적 실행(Speculative Execution)
특정 상황에서 플레이어가 취할 수 있는 행위가 제한적이라면 해당 행위가 발현되었을 때의 상태를 미리 계산해두고 플레이어의 행위에 따라 서버를 기다리지 않고 렌더링을 즉시 해줄수도 있다.

[Fig 24. Speculative Execution]

[Fig 24]를 보면 초록색 공은 플레이어의 입력에 따라 이동할 수 있는 공간이 두 가지 밖에 없다. 미리 계산된 두 가지 상태 중 플레이어의 입력에 따라 값을 반영하고 채택되지 않은 상태 값은 버린다. 둠과 퀘이크 시리즈로 유명한 이드 소프트웨어는 게임의 상태값 대신 입력에 대한 오브젝트의 모션 벡터를 클라이언트에게 전송하는 방법으로 레이턴시를 줄이는 특허를 보유하고 있다. (e.g. 한 프레임에 다수의 입력을 동시에 누르는 경우 벡터 연산으로 다음 프레임에 렌더링할 값을 만들 수 있다)

시간 조작 (Time Manipulation)

게임 월드의 시간을 되돌려서 평가하는 방법이다. 이전 장에서 다룬 예측 기술은 반응성을 높이는 반면 시간 조작은 반응성을 조금 양보하고 일관성을 높이는 기술이다.

Time Warp
서버의 입장에서 플레이어의 이벤트가 도달했을 때 월드의 시간을 과거로 잠깐 되감기 해서 플레이어의 행위를 검증하는 방법이다.

[Fig 25. Valve Developer Community | Lag Compensation]

논문에서는 타임 워프라는 용어를 썻지만 업계마다, 그리고 회사마다 부르는 용어가 조금씩은 다르다. [Fig 25]는 밸브 개발자 포럼의 위키에 등재된 렉 보정에 실린 그림이다. FPS 게임에서 플레이어가 사격을 했는데 서버의 입장에서는 표적과 거리가 조금 있는 상황이다.

서버와 클라이언트 간의 레이턴시가 존재하기 때문에 클라이언트가 인식한 세상과 서버가 인식하는 세상이 다를 수 밖에 없기 때문에 서버가 클라이언트의 입력이 발생한 시간까지 되돌려보고 사격이 발생한 시점과 물체의 위치가 일치하면 피격 판정을 내린다. 하지만 이 방식은 shot around the corner 딜레마를 만든다.

[Fig 26. Time warp]

[Fig 26]의 오른쪽 그림을 보면 파랑색 플레이어가 t1 시간에 초록색 플레이어를 사격한 상황이다. t2 시간에서 서버가 입력값을 받아봤을 때는 이미 초록색 플레이어가 안전 구역으로 이동한 상황이다. 이 때 타임워프를 적용하면 초록색 플레이어는 피격되는데 마치 난 이미 숨었는데 피격당한 것 같은 연출이 일어난다. 즉 공격자에게 어드밴티지를 줄 것인지 반대로 피해자에게 어드밴티지를 줄 것인지의 문제인데 보통은 조작감을 위해서 공격자에게 어드밴티지를 준다.

Outgoing Time Delay
서버가 의도적으로 클라이언트 마다 적용되는 방송 주기에 버퍼를 줘서 레이턴시를 균일하게 만들어 게임의 공정성과 일관성을 높이는 방식을 사용할 수 있다. 예를 들어 L_i where (1 ≤ i ≤ N) 를 i번째 클라이언트의 레이턴시라고 하고 D=max(L_i)라고 했을때 각 클라이언트 마다 D-L_i 만큼 버퍼를 두면 모든 플레이어가 서버와의 통신 주기가 균일하게 된다.

[Fig 28. Outgoing Time Delay]

NDC 2022년 프라시아 전기 팀의 발표를 보면 Outgoing Time Delay로 정지 명령이 발생한 물체의 위치의 정확성을 높이는 사례가 나온다.

Incoming Time Delay
Outgoing Time Delay와 목적은 비슷하다. Outgoing 방식은 서버가 메시지를 보낼 때 버퍼를 두는 반면, Incoming Time Delay는 클라이언트가 스스로 발생한 행위를 지연시켜서 모든 클라이언트에게 입력이 도달한 후에 동시에 상태를 갱신하는 방식이다.

[Fig 29. Incomign Delay]

Time Delay는 모두 반응성을 조금 양보하는 대신 일관성을 높여서 게임의 공정성을 더해준다. 500ms 레이턴시 까지 발생하는 게임 환경에서 상태 불일치 문제를 해결할 수 있다고 한다. 비록 반응성과 일관성 사이의 트레이드 오프가 있긴 했지만 QoE(Quality of Experience)를 조금만 희생해도 250ms 의 네트워크 환경에서 30% 정도의 성능 향상이 있다고 한다.

관련 연구 — 게임과 동시편집은 멀티-플레이어 환경에서 일정 태스크를 수행한다는 점에서 일부 교집합이 존재한다. 따라서 논문에서 소개된 결과와 관련 연구 중에서 그룹웨어에 적용되는 내용이 일부 보인다.

롤백 넷코드 (Rollback Netcode)
이건 논문에서 소개된 내용은 아니지만 시간 조작과 관련해서 1:1 격투게임에서 쓰이는 유명한 기술 중에 롤백 넷코드(Rollback Netcode)가 있다. 롤백 넷코드란 기본적으로 상대방 플레이어의 마지막 입력으로 인한 관성을 추론해서 오브젝트를 렌더링 하되, 플레이어의 입력이 시간 지연으로 너무 늦게 도착하더라도 실제 입력이 발생한 시간을 기준으로 롤백 시키는 방식이다.

Rollback Netcode 에 대해 설명하는 유튜브 영상

Time Warp는 서버 입장에서 가상으로 시간을 되돌려서 플레이어의 입력에 대한 정당성을 검증한다면 롤백 넷코드는 실제로 시간을 되돌려서 동기화를 맞춘다는 입장이다. 격투 게임은 빠른 반응성 그리고 정확한 시간에 타격해서 콤보를 완성시켜야 하는 미션이 있는데 Incoming Time Delay 기법으로 동기화를 맞추면 이런 미션을 제대로 수행하기 어려워 진다.

정상 범주 내에서의 딜레이라면 롤백 넷코드를 사용해도 플레이어들이 레이턴시를 느낄 수 없기 때문에 좋은 방법이다. 한 가지 재밌는 점은 이런 예측 및 롤백을 통한 동기화 방식을 사용하면 아래와 같은 디자인을 사용하면 플레이어가 “이게 뭐지" 하는 경험을 줄 수 있다.

스트리트 파이터 3 — K.O. 화면

상대방이 딸피인 산황에서 내가 타격할 때 상대방은 방어하거나 반응하지 못하거나 이 두 가지 갈림길이 존재한다. 만약 상대방의 방어 입력이 지연된다면 내 화면에서는 K.O.로 우선 렌더링하고 롤백 넷코드로 과거로 복구되는 경험을 하게 된다. 이런 경험을 방지하기 위해서 K.O. 팝업을 늦게 띄운다거나 슬로우 모션으로 대체할 수도 있다.

관련 오픈소스중에 GGPO SDK가 있는데, 이 오픈소스를 개발한 Tom Cannon은 현재 라이엇 게임즈 대전 격투 게임인 프로젝트 L의 프로듀서이자 테크 리드를 맡고 있다.

월드 조정(World Adjustment)

일반적으로 레이턴시(ping)가 낮으면 게임의 난이도가 상승해서 부정적인 플레이 경험을 줄 수 있다. 이를 일부 보정하고 플레이 경험을 높이기 위해 가상 세계를 조정할 수 있다.

조작감 보정 (Control Assistance)
레이턴시로 인한 플레이어 행위의 부정확성을 약간 도와주는 것이다. [Fig 30]을 보면 파랑색 플레이어가 발사한 총알은 원래 빗나가지만 가까운 오브젝트로 궤적이 변경되도록 해서 피격 판정을 해주고 있다. 또 다른 예시로는 웹 사이트에서도 물체를 드래그 할때 커서와 가까운 오브젝트를 집어주듯이 게임에서도 비슷하게 조작감을 보조해줄 수 있다.

[Fig 30. Control Assistance]

속성 스케일링(Attribute Scaling)
객체에 속한 수치나 게임 세계의 파라미터를 조정는 기법이다. 한 가지 예를 들자면 이 논문 에서는 1:1 대전 게임에서 플레이어 A가 플레이어 B의 지연을 알아채기 힘들도록 피격하는 연출 시간을 길게 가져가는 방법을 사용한다. 예를 들어 활을 이용해 활시위를 당기면 나에게서 멀어질 때는 빠르게 보여주고 플레이어 B에게 닿을 때, 아직 B에게서 응답이 오지 않았다면 약간의 슬로우 모션을 연출해서 보여주는 식이다.

[Fig 31. Attribute Scaling]

KAIST에서 발표한 HCI 연구 중 한 논문에서는 Flappy Bird 게임에서 레이턴시가 존재하면 게임의 난이도를 소폭 하향해서 Error Rate를 정상 상태로 맞추는 방안을 제안하기도 했다.

마무리

멀티-플레이어 게임 환경에서 게임 서버는 플레이어 간의 행위를 교환하고 빠르게 그리고 자주 게임 상태를 업데이트 해서 부드러운 플레이 경험을 유저들에게 제공해야 한다.

공교롭게도 과거에 비해 인터넷은 더 빨라졌지만 글로벌 원빌드 게임이 트렌드로 자리 잡으면서 국경을 넘어 더 먼거리의 플레이어와 교류해야 하고 모바일 게임 시장이 커지면서 플레이어들은 랙에 더 노출되고 있다. 이를 보정하기 위해 여러 연구가 존재한다. 이번 포스팅에서는 여러개의 논문을 분석하고 분류화해서 소개한 Survey 논문 하나를 정리했다.

--

--

scalalang2
취미로 논문 읽는 그룹

평범한 프로그래머입니다. 취미 논문 찾아보기, 코딩 컨테스트, 유니티 등 / Twitter @scalalang2 / AtCoder @scalalang