현재 3D 온라인 게임 프로젝트에서 게임서버를 제작하면서 미처 예상하지 못한 부분에서 많은 문제들이 있었고
해결해 나가면서 큰 도움이 되고 있습니다. 그 많은 문제들 중 캐릭터의 이동처리 부분이 있었습니다.
사용자가 키보드를 이용한 방향키 입력으로 이동 패킷을 서버에 보내주고 그것을 서버에서는 브로드캐스트로 뿌려주는
가장 기본적이고 간단한 방법이 있습니다. 하지만 이 방법은 엄청난 서버 부하를 가져오게 됩니다.
60프레임으로 돌아가는 게임이라고 한다면 1초에 60번이나 이동에 대한 패킷을 보내는것이 됩니다.
또한 받기도 해야겠죠. 그렇다면 어떻게 해야할까???
유저의 상태가 기존상태에서 변화되었을때만 알리게된다면 어떨까요? 기존 상태를 계속 유지하고 있다면
일정한 규칙을 가진 행동을 반복하고 있을테니 패킷을 보내지 않고 같은 처리를 계속 하도록 하고 ,
상태의 변화가 있을때만 패킷을 보내여 상태변화를 알리게 되면 서버는 이를 브로드캐스트하여 다른 클라이언트들도
해당 유저의 상태를 갱신해주는 것입니다. 이렇게 된다면 송수신 횟수를 엄청나게 줄일수 있게 됩니다.
예를들어 오른쪽 방향키를 입력하여 캐릭터를 이동시키고 있다고 가정합시다.
일정한 이동속도로 캐릭터를 계속 이동시키면서 이를 1초에 60번씩 계속 서버에 알리고 서버는 이를 똑같이
1초에 60번씩 브로드캐스트 하게 됩니다.
이동 정지에 대한 패킷은 따로 없고 패킷이 가지 않는다면 그게 바로 정지한것이 될것입니다.
다른 방법으로는 오른쪽 방향키를 처음 입력하여 캐릭터를 이동시키기 시작했을때만 패킷을 보냅니다.
서버는 이를 브로드캐스트 하여 해당 유저가 이동을 시작하였다고 알립니다.
그러면 각 클라이언트는 자체적으로 정해진 이동속도로 캐릭터를 이동시키며 1초에 60번씩 화면을 갱신합니다.
해당 유저가 방향키에서 손을 떼어서 키가 올라갔다면 캐릭터 이동 정지 패킷을 보냅니다.
서버는 이를 브로드캐스트하여 해당 유저가 정지했다고 알립니다.
그러면 또 각 클라이언트는 계산을 멈추고 해당 유저를 정지시킬겁니다.
위의 두가지 방법을 비교해봅시다.
10명의 유저가 접속해있고 한명의 유저만 초당 60프레임으로 10초동안 이동을 하였다고 가정하겠습니다.
우선 첫번째 방법은 우선 10초동안 이동하는 클라이언트가 서버로 600번 이동패킷을 보내고
서버는 접속해있는 10명에게 600번씩 전송하여 합 6000번 패킷을 전송하게 될것입니다.
총 서버는 6600번의 송수신을 하게 됩니다.
두번째 방법은 우선 이동하는 클라이언트가 이동 시작시 서버로 이동시작 패킷을 보내고
서버는 접속해있는 10명에게 한번씩 이동시작패킷을 보내게 됩니다.
총 서버는 11번의 송수신을 하게 됩니다.
두가지 방법은 6589번의 송수신 횟수가 차이납니다.
겨우 10초동안 한명의 유저만 이동하여고 총 접속인원도 10명뿐이였습니다.
이로써 두번째 방법이 얼마나 효율적인지 증명이 되었습니다.
이것이 데드 레커닝 입니다.
계속하여 패킷을 받아 위치를 갱신하여야 되지만 처음 한번만 이동정보를 받아서
패킷이 오지 않는 동안에는 처음에 받은 이동정보를 이용하여 다음 위치를 추측하여 이동시키는 것입니다.
여기서 상태 변화가 올때만 패킷을 다시 보내냐 아니면 일정 주기마다 패킷을 다시 보내냐
일정주기마다 보내는 것이면 10프레임마다 보내냐 아니면 1초마다 보내냐 이런것들은 정답이 없기 때문에
각자의 서버 상태나 혹은 게임 종류에 따라서 자기에게 알맞게 정하면 되겠습니다.
데드 레커닝이 송수신 효율에 있어서 좋다는것은 이렇게만 봐도 확실하지만 이것이 공짜로 되는것은 아닙니다.
여러가지 부가적으로 처리해줘야 하는 부분들이 있습니다.
송수신에 있어서는 지연시간이 발생할수밖에 없습니다. 이동을 요청한 유저가 보낸 패킷이 서버에 도착하기까지 걸리는
시간과 서버가 다른 유저에게 다시 뿌려주는데 걸리는 시간 , 그리고 다른 유저가 그 패킷을 받아서 처리하기까지의
지연시간이 있습니다. 그 지연시간동안 클라이언트는 기존 계산되던 방식으로 계속 해당 유저의 위치나 상태를 갱신시키
고 있기 때문에 도착한 정보와의 오차가 발생하고 이 오차만큼 캐릭터가 워프되거나 하는 문제가 생깁니다.
눈으로 확실히 식별되지 않을정도의 작은 오차라면 큰 문제가 되지 않을겁니다.
다들 한번씩 온라인게임을 하면서 경험하였을겁니다. 잘 걸어가던 캐릭터가 갑자기 뒤로 확 와지거나
일자로 걸어가다 다른방향으로 방향을 확 틀었는데 순식간에 위치가 워프되듯이 건너뛰거나 하는등
지연시간이 길어질수록 오차값이 커지게 되고 이런 문제들이 생기게 됩니다.
이런 경우 최대한 어색하지않고 자연스럽게 새로운 방향으로 이동시켜야 유저들의 불만이 없을겁니다.
어떻게하면 자연스럽게 이동할수 있을까 하는 방법이 필요합니다.
지연시간을 없앨수 있는 방법은 절대 없습니다. 그러니 오차가 있어도 이것을 어떻게 극복하여 유저들의 눈을 속여서
자연스럽게 이동하게 할수있나 심각하게 고려햐여야 할겁니다.
(턴제 게임같은 경우에는 이런걸 딱히 고려할필요가 없으니 좀 수월하겠죠 ㅎㅎ)
자연스러운 이동처리에 대해서는 다음에 다른글로 다루도록 하겠습니다.
=======
이 글을 작성하고 티스토리를 안하게 되어서 너무 오랫동안 방치했었네요.....;;
블로그를 한번 해볼까 오랜만에 찾아왔다가 생각보다 이 글을 많이들 읽으시고 문의하셨길래..
2편을 작성해보았습니다.. 너무 늦어 죄송합니다...(_ _)
2023.06.10 - [프로그래밍/서버] - 온라인 게임의 이동처리 기법 - 데드 레커닝 2 (보간 처리)
'프로그래밍 > 서버' 카테고리의 다른 글
온라인 게임의 이동처리 기법 - 데드 레커닝 2편 (보간 처리) (1) | 2023.06.10 |
---|