멀티플레이에 참여한 모든 게임 호스트들은 게임 내 모든 캐릭터 위치가 서로 같게 보여야 합니다. 이를 위해 캐릭터 위치 동기화하기가 필요합니다.
Client 1에서 움직이고 있는 캐릭터의 위치가 Client 2,3,4에서도 동기화되고 있습니다.
일반적으로 인터넷에서는 한 호스트에서 다른 호스트로 메시지를 보내는 데 걸리는 시간(레이턴시)가 발생합니다. 레이턴시와 통신량의 제한 때문에 캐릭터의 위치를 보내는 횟수와 신속성은 한계가 존재합니다. 그렇기 때문에 움직이는 캐릭터의 위치를 동기화하는 대표적인 방법은 추측 항법(dead reckoning)입니다.
한 게임 월드에서 소수의 사용자가 게임을 즐기는 캐주얼 게임에서는 각 유저들이 조종하는 캐릭터의 정보를 다른 호스트로 보낼 때는 게임 월드의 모든 유저를 1개의 P2P 그룹으로 묶어서 그들끼리 P2P간 다대다 통신을 하면 됩니다. 자세한 것은 small_game_world_sync를 참고하십시오.
하지만 게임 월드에 다수의 사용자가 게임을 즐기는 경우에는 모든 유저의 정보를 위 방식처럼 다대다로 통신하면 기하급수적으로 통신량이 증가합니다. 따라서 위 방식이 아니라, 각 유저의 시야에 들어오는 캐릭터들만 동기화 범위로 제한을 해야 합니다. 자세한 것은 large_game_world_synch를 참고하십시오.
예제 프로그램 5. 3D 월드에서 캐릭터 동기화 도 있습니다.
소수 호스트간의 게임플레이 동기화
많은 캐주얼 게임에서는 한 개의 게임 월드에 소수(보통 15개 이하)의 게임 클라이언트가 어우러져 게임을 즐깁니다. 이러한 경우 클라이언트끼리 P2P로 각자의 캐릭터 정보를 서로간 멀티캐스트를 하여도 통신량에는 큰 문제를 일으키지 않으면서 원활한 게임을 즐길 수 있습니다.
“소스 호스트간의 게임플레이 동기화"
주요 절차를 요약하면 다음과 같습니다.
• 유저가 게임 월드에 들어가기: 서버에서 해당 유저를 P2P 그룹에 참여시킵니다. (Proud.CNetServer.CreateP2PGroup 혹은 Proud.CNetServer.JoinP2PGroup)
• 유저가 게임 월드에서 나가기: Proud.CNetServer.LeaveP2PGroup를 호출해서 P2P 그룹에서 나가는 유저를 제거하거나, 유저가 서버와의 연결을 끊을 때(Proud.INetServerEvent.OnClientLeave) 자동으로 P2P 그룹에서 제거되게 내버려 둡니다.
• 각 유저의 위치를 동기화하기: 각 유저는 자신의 캐릭터의 정보를 위 P2P 그룹에게 RMI로 보냅니다. (11. Remote Method Invocation 사용 방법 참고) 각 유저의 위치를 동기화하는 대표적인 방법은 추측 항법(dead reckoning)
입니다.
다수 호스트간의 게임 플레이 동기화
대규모 멀티플레이 온라인 게임 또는 대규모전 게임(Massive multiplayer online game; MMO game)에서는 한 개의 게임 월드(예를 들어 1개의 대형 지역)에 수많은 수의 게임 클라이언트가 어우러져 게임을 즐깁니다. 이런 환경에서는, 각 캐릭터의 정보를 다른 모든 클라이언트에게 P2P로 전송하면 통신량이 기하급수적으로 늘어나는 문제가 발생합니다. 한편, 캐릭터의 위치를 다른 모든 클라이언트에게 전송할 필요가 없습니다. 왜냐하면 시야에서 너무 멀리 떨어진 캐릭터의 위치를 클라이언트에서 유지하지 않아도 되기 때문입니다.
따라서 대규모전 게임에서는 캐릭터의 위치를 클라이언트들에게 전송하되 해당 캐릭터를 시야에 두고 있는 클라이언트들에게만 보내는 것이 좋습니다. 아래 그림에서 병사 캐릭터를 조종하는 클라이언트 B는 서버에게 캐릭터의 상태(위치 등)을 보내줍니다. 그러면 서버는 캐릭터의 위치를 보내되, 병사를 시야에 두고 있는 클라이언트 A,C에게만 보냅니다. 클라이언트 D는 병사를 시야에 두고 있지 않으므로 캐릭터의 위치를 받지 않습니다. 이렇게 함으로 클라이언트 D로 보내야 하는 통신량을 절감합니다. 이를 보고 가시 영역 필터링이라고 칭합니다.
대규모전 게임에서의 가시 영역 필터링(서버 경유 방식)
가시 영역 필터링을 정리하면 아래와 같습니다.
• 클라이언트에서 서버로 자기의 캐릭터 상태를 전송합니다.
• 서버에서 각 캐릭터 상태를 받아 보유합니다. 그리고 그 캐릭터를 볼 수 있는 다른 클라이언트들을 선별해서 그들에게만 캐릭터 정보를 보내줍니다.
위의 가시영역 필터링은 서버를 경유해서 통신을 하는 전통적인 방식입니다. 이러한 방식에서는 모든 멀티캐스트를 서버가 담당하기 때문에 서버에 과부하가 걸리는 단점이 있습니다. 하지만 ProudNet은 이 문제를 고성능 P2P 그루핑 및 P2P 통신 기술을 통해 성능을 향상할 수 있습니다. 이를 혼합 위상 네트워킹 기법(등록 특허 제10-0812019호) 이라고 칭합니다. ProudNet을 쓰는 프로젝트에 한해 이 기술을 쓸 수 있도록 허가되어 있습니다. ProudNet의 매우 빠른 P2P 그루핑 성능은 이 기법을 가능하게 해줍니다.
혼합 위상 네트워킹을 간단히 요약하자면, 캐릭터의 위치를 서버를 통해 멀티캐스트하지 않고 직접 P2P로 타 클라이언트에게 전송하면서 멀티캐스트 범위를 가시 영역으로 제한하는 방법입니다.
대규모전 게임에서의 가시 영역 필터링(혼합 위상 네트워킹 방식)
ProudNet과 혼합 위상 네트워킹을 응용한 동기화 방법은 다음과 같습니다. 설명의 보충을 위해 이 ProudNet의 샘플 5. 3D 월드에서 캐릭터 동기화 에서의 소스 위치와 더불어 설명하겠습니다.
서버에서는 각 클라이언트가 조종하는 캐릭터의 위치를 저장할 공간을 두어야 합니다. (5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CRemoteHero 참고)
클라이언트에서는 자기 캐릭터(5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CLocalHero 참고) 및 타 클라이언트의 동기화되는 캐릭터(synch_world_sample의 클라이언트 소스에서 CRemoteHero_C 참고)를 두어야 합니다. 그리고 서버에서는 각 캐릭터마다 '캐릭터를 볼 수 있는 클라이언트들'을 P2P 그룹으로 묶은 Proud.HostID 변수를 두어야 합니다. (5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CRemoteHero.m_viewersGroupID 참고)
클라이언트에서는 자신의 캐릭터의 위치를 일정 시간마다 서버에게 전송합니다. 그리고 서버는 그것을 받아 저장합니다. (5. 3D 월드에서 캐릭터 동기화
의 클라이언트 소스에서 CLocalHero::FrameMove 참고)
클라이언트에서 조종하는 캐릭터가 다른 클라이언트의 가시 영역에 들어갔는지, 나갔는지 여부를 서버에서 일정 시간마다 체크합니다. (5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CRemoteClient::FrameMove 참고) 이때 서버에서는 캐릭터가 가시 영역에서의 진입 또는 이탈이 확인될 때마다 그 캐릭터의 등장 혹은 소멸 메시지를 해당 클라이언트에게 RMI로 전송하고, 그 '캐릭터를 볼 수 있는 클라이언트들'에 추가 혹은 제거를 해야 합니다.
만약 캐릭터가 클라이언트의 가시 영역에 들어갔음이 확인되면, 해당 클라이언트에게 출현 RMI를 전송하고 (5. 3D 월드에서 캐릭터 동기화
의 RemoteHero_Appear RMI 참고) 해당 클라이언트를 '캐릭터를 볼 수 있는 클라이언트들' 에 추가합니다. (3D 월드에서 캐릭터 동기화 의 서버 소스에서 CRemoteClient::FrameMove 참고)
만약 캐릭터가 클라이언트의 가시 영역에서 나갔음이 확인되면, 해당 클라이언트에게 소멸 RMI를 전송하고 (5. 3D 월드에서 캐릭터 동기화
의 RemoteHero_Disappear RMI 참고) 해당 클라이언트를 '캐릭터를 볼 수 있는 클라이언트들' 에서 제거합니다. (3D 월드에서 캐릭터 동기화 의 서버 소스에서 CRemoteClient::FrameMove 참고)
클라이언트가 처음 게임 월드에 들어갈 때, 클라이언트는 자기 캐릭터의 '캐릭터를 볼 수 있는 클라이언트들'을 가리키는 P2P 그룹 ID를 얻어와야 합니다. (5. 3D 월드에서 캐릭터 동기화
의 NotifyLocalHeroViewersGroupID RMI 참고) 이 값을 근거로 클라이언트는 일정 시간마다 자기 캐릭터의 위치를 P2P로 전송합니다. 이때 추측 항법(dead reckoning) 기법이 필요할 것입니다. (3D 월드에서 캐릭터 동기화 의 클라이언트 소스에서 CClient::P2P_LocalHero_Move 참고)
클라이언트의 자기 캐릭터가 게임 월드에 등장하는 경우는 '캐릭터가 클라이언트의 가시 영역에 들어갔음' 상황과 같습니다. (5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CSynchWorldServerDlg::RequestLocalHeroSpawn 참고) 반대로, 클라이언트의 자기 캐릭터가 게임 월드에서 제거되는 경우는 '캐릭터가 클라이언트의 가시 영역에서 나갔음' 상황과 같습니다. (5. 3D 월드에서 캐릭터 동기화
의 서버 소스에서 CSynchWorldServerDlg::OnClientLeave 참고)
혼합 위상 네트워킹 방식에서는 클라이언트에서 너무 많은 수의 클라이언트들에게 지나치게 많은 송신량이 발생할 수 있습니다. 이를 예방하기 위해 11. 송신량 자동 조절 기능 (Throttling) 및 6.9 직접 P2P 통신과 relay 통신의 성능 차이
참고를 권장합니다.