estou fazendo um jogo de física rápido que é um hóquei na mesa. Com dois marretas e um disco. O jogo roda em iphone / ipad e eu estou fazendo a parte multiplayer através do GameCenter.
É assim que o sistema de rede funciona. O cliente que iniciar a partida será estabelecido como servidor e quem aceitar a solicitação de partida será o cliente.
O 'servidor' tem a física em execução e a resposta é imediata e o cliente também tem a física em execução, para que pareça suave entre a troca de mensagens. O que faço como servidor é que eu envio ao cliente minha velocidade de disco e minha posição e o cliente ajusta sua velocidade / posição de disco relacionada ao servidor para mantê-lo sincronizado. Caso contrário, a física dessincroniza e estraga tudo.
Quando a latência da rede é boa, abaixo de 100ms, os resultados são muito bons, eu tenho um jogo fácil de jogar no lado do cliente e o comportamento estranho é mínimo. O problema ocorre quando o atraso é de cerca de 150 a 200ms. Nesse caso, acontece que o meu disco do cliente já atingiu uma direção invertida, mas recebe uma mensagem de atraso do servidor e recua um pouco, causando uma sensação estranha no comportamento da bola.
Eu li algumas coisas sobre isso:
Clique em exemplo de sincronização
Wikipedia sobre sincronização de relógio
Então, como posso resolver isso? Tanto quanto li a melhor opção que tenho, é fazer uma sincronização de relógio no servidor / cliente com um carimbo de data e hora, para que, quando recebo mensagens de atraso relacionadas ao meu relógio, eu simplesmente as ignore e permita que a simulação dos clientes faça o seguinte. trabalho. Vocês concordam com isso? E como estou enviando dados não confiáveis (UDP), posso receber mensagens atrasadas ou fora de ordem.
Se essa é a melhor abordagem, como faço para implementar a sincronização do relógio. Eu li as etapas de como fazê-lo, mas não o entendi direito.
Isso diz que:
- O cliente carimba a hora local atual em um pacote de "solicitação de hora" e envia para o servidor.
- Após o recebimento pelo servidor, o servidor marca o horário do servidor e retorna
- Após o recebimento pelo cliente, o cliente subtrai o horário atual do horário enviado e divide por dois para calcular a latência. Ele subtrai a hora atual da hora do servidor para determinar o delta do horário cliente-servidor e adiciona a meia latência para obter o delta do relógio correto. (Até agora, este algothim é muito semelhante ao SNTP)
- O cliente repete as etapas 1 a 3 cinco ou mais vezes, pausando alguns segundos a cada vez. Outro tráfego pode ser permitido nesse ínterim, mas deve ser minimizado para obter melhores resultados. Os resultados dos recebimentos de pacotes são acumulados e classificados na ordem de menor latência para maior latência. A latência mediana é determinada escolhendo a amostra do ponto médio dessa lista ordenada.
- Todas as amostras acima de aproximadamente 1 desvio padrão da mediana são descartadas e as demais amostras são calculadas usando uma média aritmética.
Seguindo este exemplo, eu teria isso:
Vamos fingir que o jogo foi carregado e o tempo do meu cliente é 0 agora, então eu envio ao servidor que o meu tempo é 0.
As mensagens levam 150ms para chegar ao servidor, mas o relógio do servidor já foi iniciado e fica 1 segundo à frente do cliente. Quando o servidor receber a mensagem, o horário será: 1.15 e envia esse horário para o cliente, estamos bem? Vamos fingir que nosso atraso é constante a 150ms.
Agora, o cliente recebe o horário 1,15 e subtrai o horário atual do horário enviado e divide por dois para calcular a latência. Qual é: 0,3 - 0 = 0,3 / 2 -> 150ms.
Ele subtrai a hora atual da hora do servidor para determinar o delta do horário cliente-servidor e adiciona a meia latência para obter o delta do relógio correto:
Hora do cliente: 0,3 Hora do servidor 1,15
0,3 - 1,15 = 0,85 + latência (0,15) = 1
Como isso é sincronizado? O que estou perdendo?
É a minha primeira vez em multiplayer e experiência em rede, então estou um pouco confuso.
Obrigado.
Respostas:
O algoritmo publicado estava correto, mas no seu exemplo você está esquecendo o tempo que leva para o pacote do servidor chegar ao cliente, portanto:
Agora, como você pode ver, se o cliente alterasse o relógio para 1,15, seria 0,15 atrás do servidor, é por isso que você precisa ajustar o Ping (também conhecido como Round Trip Time [RTT]). Aqui está o cálculo do tempo delta completo realizado em várias etapas:
Isso nos dá o tempo delta correto de 1,00 segundos
fonte