캐릭터 위치 동기화
Last updated
Last updated
멀티 플레이에 참여한 모든 게임 호스트들은 게임 내 모든 캐릭터 위치가 서로 같게 보여야 하는데, 이를 위해 캐릭터 위치 동기화가 필요합니다.
일반적으로 인터넷에서는 한 호스트에서 다른 호스트로 메시지를 보내는 데 걸리는 시간(레이턴시)가 발생합니다. 레이턴시와 통신량의 제한 때문에 캐릭터의 위치를 보내는 횟수와 신속성은 한계가 존재합니다. 그렇기 때문에 움직이는 캐릭터의 위치를 동기화하는 대표적인 방법으로 추측 항법 (dead reckoning) 을 사용합니다.
한 게임 월드에서 소수의 사용자가 게임을 즐기는 캐주얼 게임에서는 각 유저들이 조종하는 캐릭터의 정보를 다른 호스트로 보낼 때는 게임 월드의 모든 유저를 1개의 P2P 그룹으로 묶어서 그들끼리 P2P 간 다대다 통신을 하면 됩니다.
하지만 게임 월드에 다수의 사용자가 게임을 즐기는 경우에는 모든 유저의 정보를 위 방식처럼 다대다로 통신하면 기하급수적으로 통신량이 증가합니다. 따라서 위 방식이 아니라, 각 유저의 시야에 들어오는 캐릭터들만 동기화 범위로 제한을 해야 합니다.
많은 캐주얼 게임에서는 한 개의 게임 월드에 소수(보통 15개 이하)의 게임 클라이언트가 어우러져 게임을 즐깁니다. 이러한 경우 클라이언트끼리 P2P로 각자의 캐릭터 정보를 서로 간 멀티캐스트 를 하여도 통신량에는 큰 문제를 일으키지 않으면서 원활한 게임을 즐길 수 있습니다.
게임 월드에 들어가기: 서버에서 해당 유저를 P2P 그룹에 참여시킵니다. CreateP2PGroup 혹은 JoinP2PGroup
게임 월드에서 나가기: LeaveP2PGroup를 호출해서 P2P 그룹에서 나가는 유저를 제거하거나, 유저가 서버와의 연결을 끊을 때 Proud.INetServerEvent.OnClientLeave가 자동으로 P2P 그룹에서 제거되게 내버려 둡니다.
각 유저의 위치를 동기화하기: 각 유저는 자신의 캐릭터의 정보를 위 P2P 그룹에게 RMI로 보냅니다.
C++ 11 함수 | C# 함수 | 설명 |
---|---|---|
대규모 멀티 플레이 온라인 게임 또는 대규모전 게임(MMO)에서는 한 개의 게임 월드(예: 1개의 대형 지역)에 수 많은 게임 클라이언트가 어우러져 게임을 즐깁니다.
이런 환경에서는, 각 캐릭터 정보를 다른 모든 클라이언트에게 P2P로 전송하면 통신량이 기하급수적으로 늘어나는 문제가 발생합니다. 따라서 대규모전 게임에서는 캐릭터의 위치를 클라이언트들에게 전송하되 해당 캐릭터를 시야에 두고 있는 클라이언트들에게만 보내는 것이 좋습니다.
아래 그림에서 캐릭터를 조종하는 클라이언트 B는 서버에게 캐릭터의 상태(위치 등)을 보내줍니다. 그러면 서버는 캐릭터의 위치를 보내되, 병사를 시야에 두고 있는 클라이언트 A,C에게만 보냅니다. 클라이언트 D는 병사를 시야에 두고 있지 않으므로 캐릭터의 위치를 보내지 않아 통신량을 절감합니다.
이를 가시 영역 필터링이라고 칭합니다.
가시 영역 필터링을 정리하면 아래와 같습니다.
클라이언트에서 서버로 자기의 캐릭터 상태를 전송합니다.
서버에서 각 캐릭터 상태를 받아 보유합니다. 그리고 그 캐릭터를 볼 수 있는 다른 클라이언트들을 선별해서 그들에게만 캐릭터 정보를 보내줍니다.
위의 가시 영역 필터링은 서버를 경유해서 통신을 하는 전통적인 방식으로 모든 멀티 캐스트를 서버가 담당하기 때문에 과부하가 걸리는 단점이 있습니다.
ProudNet은 이 문제를 매우 빠른 고성능 P2P 그루핑 및 P2P 통신 기술을 통해 성능이 향상되는데, 이를 혼합 위상 네트워킹 기법(등록 특허 제10-0812019호)이라고 칭합니다.
이 기술은 캐릭터 위치를 서버를 통해 멀티 캐스트를 하지 않고 직접 P2P로 타 클라이언트에게 전송하면서 멀티캐스트 범위를 가시 영역으로 제한하는 방법으로, ProudNet을 쓰는 프로젝트에 한해 쓸 수 있도록 허가되어 있습니다.
서버에서는 각 클라이언트가 조종하는 캐릭터의 위치를 저장할 공간을 두어야 합니다.
클라이언트에서는 자기 캐릭터 및 타 클라이언트의 동기화되는 캐릭터를 두고 서버에서는 각 캐릭터마다 캐릭터를 볼 수 있는 클라이언트들을 P2P 그룹으로 묶은 Proud.HostID 변수를 둡니다.
클라이언트는 자신의 캐릭터 위치를 일정 시간마다 서버에게 전송하면 서버는 그것을 받아 저장합니다.
클라이언트에서 조종하는 캐릭터가 다른 클라이언트의 가시 영역에 있는지를 서버에서 일정 시간마다 체크합니다. 이때 서버에서는 캐릭터가 가시 영역 진입 또는 이탈이 확인될 때마다 그 캐릭터의 등장 혹은 소멸 메시지를 해당 클라이언트에게 RMI로 전송하고, 그 캐릭터를 볼 수 있는 클라이언트들에 추가 혹은 제거를 해야 합니다.
캐릭터가 클라이언트의 가시 영역 진입이 확인되면, 해당 클라이언트에게 출현 RMI를 전송하고 캐릭터를 볼 수 있는 클라이언트들 에 추가합니다.
캐릭터가 클라이언트의 가시 영역 이탈이 확인되면, 해당 클라이언트에게 소멸 RMI를 전송하고 캐릭터를 볼 수 있는 클라이언트들 에서 제거합니다.
클라이언트가 처음 게임 월드에 들어갈 때, 클라이언트는 자기 캐릭터의 캐릭터를 볼 수 있는 클라이언트들을 가리키는 P2P 그룹 ID를 얻어와야 합니다. 이 값을 근거로 클라이언트는 일정 시간마다 자기 캐릭터의 위치를 P2P로 전송할 때 추측 항법 (dead reckoning) 기법이 필요합니다.
클라이언트의 자기 캐릭터가 게임 월드에 등장하는 경우는 캐릭터가 클라이언트의 가시 영역에 진입 상황과 같습니다. 반대로, 클라이언트의 자기 캐릭터가 게임 월드에서 제거되는 경우는 캐릭터가 클라이언트의 가시 영역에서 이탈 상황과 같습니다.
혼합 위상 네트워킹 방식에서는 클라이언트에서 너무 많은 수의 클라이언트들에게 지나치게 많은 송신량이 발생할 수 있습니다.
이를 예방하기 위해 송신량 자동 조절 기능 (Throttling) 및 P2P 통신 을 참고하시기 바랍니다.
Proud.CNetServer.CreateP2PGroup
Nettention.Proud.NetServer.CreateP2PGroup
P2P 그룹을 생성합니다.
Proud.CNetServer.JoinP2PGroup
Nettention.Proud.NetServer.JoinP2PGroup
이미 존재하는 P2P 그룹에 peer를 추가합니다.
Proud.CNetServer.LeaveP2PGroup
Nettention.Proud.NetServer.LeaveP2PGroup
P2P 그룹에서 멤버를 퇴장 시킵니다.
Proud.CNetServer.OnClientLeave
Nettention.Proud.NetServer.ClientLeaveHandler
클라이언트가 연결을 종료하면 발생하는 이벤트입니다.