RTS 게임 프로토콜


18

멀티 플레이어 RTS 게임에 대해 생각하고 있습니다. 내가 돌아갈 수없는 부분은 단위 움직임을 동기화 유지하는 것입니다. 장치 A를 XY로 이동 시키려면 다른 클라이언트로 릴레이하는 서버로 다시 통신해야합니다.

커뮤니케이션이 어떻게 생겼는지 궁금합니다. 내가 장치 A를 JZ에서 XY로 옮기고 있다고 서버와 통신하겠습니까? 어쩌면 당신은 대신에 좌표로 움직임 좌표를 전달해야합니까? 한 클라이언트에서 다른 클라이언트로 유닛의 이동을 전달하는 가장 효율적인 방법은 무엇입니까?

편집하다

이것은 stackoverflow에서 다시 게시 된 질문입니다 . 이 사이트가이 질문에 대한 더 좋은 장소라는 것을 알았습니다.

그 게시물에서 더 나은 답변 중 하나 :

클라이언트-서버 네트워킹 패러다임을 사용하려고한다고 생각하십니까? 이 경우 클라이언트가 장치의 실제 위치를 처리하도록 신뢰할 수없는 경우 해당 작업을 서버에 위임해야합니다. 그런 다음 각 클라이언트별로 명령 목록을 가져 와서 각 장치의 이동을 계산합니다.이 작업이 완료되면 다음에 각 클라이언트와 관련된 각 장치의 위치를 ​​전체 맵 또는 보기 기준으로) 프로세스를 다시 시작하십시오.


2
대답은 실제로 사용하려는 방법에 따라 다릅니다. 클라이언트-클라이언트 또는 클라이언트-서버. 클라이언트 대 서버는 더
쉬우나

답변:


25

서버에서 각 클라이언트로 모든 장치의 위치를 ​​동기화하지 않으려 고합니다. 그 소요됩니다 방법 당신이 필요로하는 것보다 더 많은 대역폭을. 또한 보간 / 외삽 유닛 위치 등을 처리해야합니다. 전문 RTS의 클라이언트 / 서버 사용은 거의 없습니다!

대신 플레이어의 명령 만 보내려고합니다. 플레이어가 클릭 할 때 유닛을 즉시 움직이지 않고, 앞으로 몇 지점에서 보통 두 프레임 만 이동 명령을 대기시킵니다. 모든 사람은 자신의 명령을 모든 사람에게 보냅니다. 몇 프레임 후에 모든 사람이 모든 명령을 실행하며 게임이 결정론 적이므로 모두 동일한 결과를 보게됩니다.

단점은 모든 플레이어가 가장 느린 플레이어만큼 느리다는 것입니다. 누군가가 명령을 보내는 데 뒤쳐지면 모두가 속도를 늦추고 그를 따라 잡기를 기다려야합니다 (Starcraft 2에서 "XXX는 게임 속도를 늦 춥니 다) " 대화 상자).


실제로 일반적으로 수행되는 작업이 하나 더 있습니다. 서버를 모두 제거하십시오 . 모든 클라이언트가 다른 모든 클라이언트에게 명령을 보내도록하십시오. 이것은 지연 감소 (대신에 당신에게서가는 명령을 -> 서버 -> 상대는, 그냥 당신에게서 간다 -> 상대) , 쉽게 코딩없는 코드로부터 더 이상 필요가 별도의 서버 수 있습니다. 이러한 종류의 아키텍처를 P2P ( Peer-to-Peer )라고합니다.

단점은 이제 갈등을 해결하는 방법이 필요하지만 대부분의 RTS에서 플레이어의 명령이 서로 독립적이기 때문에 일반적으로 큰 문제는 아닙니다. 또한 확장 성이 좋지 않습니다. 새 플레이어를 추가 할 때마다 모든 플레이어가 명령을 보내야합니다. P2P를 사용하여 MMO RTS를 만들지 않을 것입니다.


이 설정 (P2P를 사용하여 명령 만 전송) 은 Starcraft, C & C 및 AoE를 포함한 대부분의 RTS가 작동하는 방식이며 AoE가 28.8kbps 연결에서 1500 대를 지원할 수있는 유일한 방법 입니다.

(AoE의 네트워킹 이미지)

P2P RTS 작성을위한 몇 가지 추가 정보는 다음과 같습니다.

  • 명백한 이유로,이 설정은 게임에서 고정 단계 시간을 사용하는 경우에만 작동합니다 . 계산 결과가 프레임 속도에 의존하지 않기를 바랍니다! 고정 단계는 대부분의 경우 작업하기가 쉬우므로 문제가되지 않습니다.
  • 이 작업을 수행하려면 모든 명령의 결과가 완전히 결정적 이어야합니다 .
    • 하나의 시스템 (예 : 32 비트 Windows)으로 자신을 제한하고 모든 클라이언트가 동일한 실행 파일을 사용하도록 강제하는 경우 일반적으로 매우 쉽습니다. 정렬되지 않은 컬렉션을 반복 할 때는 매우주의해야합니다 . 기타
    • 다른 플랫폼에서 게임을 플레이 할 수있게하려는 경우 (또는 Linux의 경우와 같이) 클라이언트가 코드를 직접 컴파일 할 수있게하는 경우 이는 매우 어렵습니다. 뿐만 아니라 꽤 많은 다른 구현 사용 보장 다른 시스템 라이브러리입니다 rand(), cos()등,하지만 거의 모든 부동 소수점 연산이 밖으로 질문 합니다 ( 여기 , 여기 , 그리고 여기에 ) ! 이 경우 클라이언트 서버를 사용하는 것이 좋습니다.
  • 당신은 desync 버그를 (이, 신뢰 나에게, 당신이 감지 적어도 디버깅하는 동안, 가끔 모든 단위의 위치 각을 보낼거야 것이다 있다). 최종 게임에서 당신이 그것을 유지하는지 여부는 당신에게 달려 있습니다. 나는 적어도 일부 장치를 동기화하거나 일종의 체크섬을 사용하여 해킹 시도를 감지합니다.

좋은 소식입니다. 작은 컴파일러, 심지어 동일한 컴파일러조차도 최적화, 디버그 / 릴리스 및 기타 플래그로 인해 결과가 변경 될 수 있습니다. 조심해!
피터 Ølsted

14

TCP 네트워크 RTS를 만들었는데 , 명령 결과 대신 명령 자체를 전달했습니다 . 예를 들어, 플레이어는 이동 명령을 내립니다. 해당 클라이언트에 따라 이동 순서가 유효하면 서버로 전송됩니다. 그런 다음 서버는 서버를 검증하고 실행하는 모든 클라이언트에게 다시 보냅니다.

따라서 모든 클라이언트 컴퓨터가 게임을 자체적으로 실행하면 서버 코드는 메시지를 받아 모든 클라이언트에게 다시 보냅니다. 클라이언트가 이동 명령을 내리면 서버에서 다시받을 때까지 실행을 시작하지 않습니다.

서버는 명령을 실행할 수있는 '틱'번호를 전송합니다.이 숫자는 '현재'눈금보다 몇 번의 눈금입니다. 이런 식으로 모든 명령을 모든 컴퓨터에서 동일한 '틱'으로 실행할 수 있습니다.

이 방법의 장점 중 하나는 명령을 확인하기 위해 개별 클라이언트 시스템에 의존하지 않는다는 것입니다. 이동 결과를 통과하면 해킹하여 유닛을 더 빨리 이동할 수 있습니다. 모든 클라이언트는 동일한 명령을 실행해야하며 한 시스템에서 다르게 실행하면 분명합니다.

서버로 보내기 전에 클라이언트 측 명령을 검증 할 필요는 없지만 이론 상으로는 네트워크 트래픽을 절약합니다. 동일한 유효성 검사 코드를 사용하여 UI에 이동이 가능하다는 것을 알려주므로 추가 코드를 작성할 필요가 없었습니다.

메시지가 어떻게 생겼는지에 관해서. 첫 네트워크 게임 이었기 때문에 초 고효율에 대해서는 신경 쓰지 않았습니다. 명령을 문자열로 전달했습니다. 명령 형식은 다음과 같습니다."<player_id>:<command>:<parameters>"

고려 된 예제의 경우 이동 명령은 다음과 같습니다 "3:move:522:100:200". 플레이어는이 방법 3으로 원하는 move단위 522로 ( 100, 200).

서버는 다음과 같이 눈금 번호가 첨부 된 명령을 보낸 클라이언트를 포함하여 모든 클라이언트에 명령을 전달합니다 "153238:3:move:522:100:200".

그런 다음 클라이언트가 153238 틱이 실행될 때이 명령을 모두 실행합니다.


질문에 조금 더 많은 정보를 추가했습니다. SO의 답변은 귀하가 말한 것에 반하는 것으로 보이며 자세한 내용을 논의하고 싶습니다.
Darthg8r

예, 그것은 그것을하는 또 다른 방법이지만, 명령이 아닌 많은 게임 상태를 통과시키는 것이 더 많은 일인 것 같습니다. 내 게임은 모든 것이 각 클라이언트 컴퓨터에서 실행될 수있을 정도로 간단했다. MMO 또는 Minecraft와 같은 경우 클라이언트 측에서 전체 시뮬레이션을 실행하지 않으므로 각 클라이언트와 관련된 정보 만 개별적으로 전달합니다.
Philip
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.