Today I Learn

[TIL][C++] 250623 MMO 서버 개발 41일차: 클라이언트를 믿지 못하는 서버의 충돌 판정 처리

pledge24 2025. 6. 24. 00:19
주의사항: 해당 글은 일기와 같은 기록용으로, 다듬지 않은 날것 그대로인 글입니다. 

클라이언트를 믿지 못하는 서버의 충돌 판정 처리

  • 온라인 게임을 제작할 때 항상 명심해둬야 하는 사실은, “클라이언트를 절대 믿어선 안된다”는 것이다. 개발자 입장에서 가져야 할 태도는 [클라는 모든 소스코드와 데이터가 공개되어 있고, 모든 보안은 서버에서 처리한다]가 되어야 한다.

 

온라인 게임에서의 충돌 판정 처리의 차이점

  • 문제는 이러한 태도와 사실을 기반으로 온라인 게임을 제작하기 시작하면 게임 엔진에서 제공하는 충돌 판정을 사용하지 못하는 경우가 발생하게 된다. 만약, 온라인 게임이 아닌 오프라인 게임(콘솔 게임류)이라면 아래와 같이 진행되겠지만,
    1. 캐릭터가 나무 쪽으로 이동한다.
    2. 캐릭터가 나무에 닿으면 나무의 콜라이더와 충돌 판정이 발생한다.(게임 엔진에 의해)
    3. 충돌 판정에 의해 나무로 뚫고 이동하는 것을 막는다.
  • 온라인 게임인 경우 클라이언트 프로그램의 충돌 판정을 사용할 수 없기 때문에 아래와 같이 진해되어야 한다.
    1. 서버에서 캐릭터 1의 이동을 처리한다.
    2. 캐릭터가 나무에 충돌했는지 계산하고, 나무와의 충돌 판정이 발생한다.(서버 내부 코드에 의해)
    3. 충돌 판정에 의해 나무를 뚫고 이동하는 것을 막는다.

서버에서 충돌 처리를 할 경우 발생하는 문제

  • 대부분의 게임의 경우, 서버는 10Hz(100ms) 보다 높은 업데이트 주기를 가져갈 수 없기 때문에 모든 충돌 판별을 전부 다 하기엔 무리가 있다. 왜냐하면 업데이트 주기 사이에 발생한 이벤트들의 타이밍 구분이 되지 않기 때문이다.

 

대표적인 예시: FPS 장르의 Super Bullet

  • FPS 장르에서 사용하는 총기의 연사 속도는 750 RPM이거나 그 이상이 된다. 즉, 분당 발사할 수 있는 총알이 750개 이상이며, 총알 하나가 80ms 마다 발사되거나 80ms 보다 짧은 시간에 발사된다는 것이다.
  • 만약, 서버가 100ms를 업데이트 주기를 가지고, 모든 총알은 히트스캔 방식이 아닌 투사체 방식(projectile)이라면, 각 총알 투사체들은 100ms 보다 빠르게 연사 되기 때문에, 한 번의 업데이트 주기에 여러 개의 총알이 발사 처리 및 이동 + 피격 처리가 되어야 한다.
  • 이렇게 발사된 두 총알을 하나의 캐릭터가 맞았다면, 사람 1을 컨트롤하는 유저의 입장에선, 한 번에 2배의 피해를 받는, 일명, “Super Bullet”에 의해 피해를 받는 경험을 하게 된다.
// 이전 업데이트 주기의 상황
- - [사람1]
// 현재 업데이트 주기의 상황
    [사람1] - -
    
// 현재 업데이트 주기의 시뮬레이션 결과
// 기대한 결과: 첫번째, 두번째 나눠서 피해를 입음
// 실제 결과: 첫번째, 두번째 한 번에 피해를 입음

 

또 다른 문제: 이게 왜 맞는 거지?

  • 서버에서 업데이트 주기가 느릴수록 클라이언트에서 진작에 뜬 자리에 계속 캐릭터가 남아있기 때문에 해당 위치로 날아오는 모든 투사체를 다 맞게 된다.
  • 문제는 기본적으로 총알이 날아가는 속도는 굉장히 빠르기 때문에, 느린 업데이트 주기에 의한 안 맞을 총알에 피격되는 횟수가 꽤 많다는 것이다.

 

FPS에서 발생하는 Super Bullet 문제의 해결책: 보다 빠른 업데이트 주기

  • 무식하지만 가장 효과적인 방법이라고 본다. 서버의 업데이트 주기를 10hz가 아닌 30hz까지 올려서 Super Bullet 문제를 유의미한 정도까지 해결할 수 있다.
  • 그래서 실제로 FPS 게임들은 30Hz~60hz 정도의 높은 업데이트 주기를 유지한다.

 

MMORPG 장르의 충돌 판정 처리

  • 사실 위와 같이 30hz로 높은 업데이트 주기를 가져야 한 하는 경우는 많지 않다. (속도가 빠른 오브젝트가 있는 레이싱 게임이나 FPS 게임에서만 고려하는 듯하다) MMORPG의 경우도 10hz만 들고 가도 전반적인 충돌 판정에 큰 문제는 없다.
  • 그럼에도 불구하고, 워낙 MMORPG 게임 서버가 처리해야 할 작업이 많기 때문에 모든 충돌 처리를 도맡아서 하기에는 문제가 있다. 예를 들어, 공중 도약 후, 지면과 충돌이 발생하면 충격파를 발생시키는 스킬을 기획했다면, 서버는 언제쯤 지면에 충돌이 났음을 알 수 있을까? 캐릭터의 위치를 추적해서 지면과 닿는 시점을 추적해야 할까?
  • 정석적인 방법은 그렇겠지만, 당연히 이 부분은 서버가 먹는 부하도 생각해야 한다. 데디케이티드 서버로 돌리는 “한 판” 단위의 게임 같은 경우, 아예 게임 엔진을 올려서 시뮬레이션 돌릴 수 있겠지만, MMORPG 같은 경우 그럴 수 없다.
  • 결국, “클라이언트의 힘을 빌려 어느 정도 충돌 판정을 받고, 서버에서 러프하게 검사하는 식으로 만들게 된다.”