Compensação de atraso com jogos 2D em rede

31

Eu quero fazer um jogo 2D que é basicamente um jogo de sandbox / atividade baseado em física. Há algo que eu realmente não entendo. A partir da pesquisa, parece que as atualizações do servidor devem ter apenas a cada 100ms. Eu posso ver como isso funciona para um jogador, pois ele pode simular simultaneamente a física e compensar o atraso por meio de interpolação.

O que eu não entendo é como isso funciona para atualizações de outros jogadores. Se os clientes são notificados apenas das posições dos jogadores a cada 100ms, não vejo como isso funciona, porque muita coisa pode acontecer em 100ms. O jogador poderia ter mudado de direção duas vezes mais ou menos naquele tempo. Fiquei me perguntando se alguém teria alguma idéia sobre este assunto.

Basicamente, como isso funciona para filmar e coisas assim?

obrigado

jmasterx
fonte

Respostas:

58

Resumo para quem não gosta de respostas longas ...

Isso pode ser feito, mas é impossível fazer uma física multiplayer perfeita, se houver alguma latência. Por que a latência afeta a física é explicada e, em seguida, são fornecidas dicas para reduzir o impacto da latência em sua simulação de física.


Criar um jogo de física multiplayer pode ser cheio de perigos. É impossível criar uma experiência física multiplayer "perfeita" online. Há coisas que você pode fazer para melhorar, mas não há como fazer uma física perfeita assumindo alguma latência.

O problema é que a física precisa ser rápida e responsiva para ser realista, mas ao mesmo tempo deve ser calculada com base nas ações combinadas de TODOS os fatores - significando as ações combinadas de todos os jogadores. E se houver latência, isso não pode ser feito em tempo real.

Cabe a você, como desenvolvedor, decidir se pode manter os diferentes fatores sob controle e entender que a experiência do jogador se degradará se a latência se tornar muito alta. Se você pode viver com isso (e seus jogadores podem), então vá em frente. Veja no final deste post algumas notas sobre como você pode manter as coisas funcionando de maneira mais suave.

Um exemplo para mostrar como as coisas podem ficar confusas

Imagine um jogo em que dois jogadores (clientes) estejam conectados a um servidor. Leva 100 milissegundos (1/10 de segundo) para que uma mensagem passe pela Internet do cliente para o servidor. Quando um jogador faz alguma coisa, uma mensagem é enviada ao servidor dizendo o que eles fizeram. O servidor então transmite a mensagem aos outros jogadores, para que todos saibam o que o jogador interino fez.

Agora crie um cenário em que dois jogadores tenham uma caixa no chão, que é um objeto de física. O jogador A bate de um lado, enviando-o em alguma direção. No entanto, ao mesmo tempo, o jogador B bate no outro lado, enviando outra direção.

Vejamos maneiras diferentes de lidar com isso e quais seriam os resultados ...

E se a física for calculada apenas no servidor?

Suponha que tenhamos a física calculada apenas no servidor. O jogador A envia a mensagem "Eu bati na caixa desta maneira" para o servidor, 1/10 segundo depois o servidor recebe a mensagem. O jogador B envia a mensagem "Eu bati na caixa dessa outra maneira". O servidor calcula a alteração física a partir da combinação das duas ações e envia uma mensagem de volta aos dois jogadores dizendo: "OK, ele se move dessa maneira". Física perfeita é realizada, com base nas ações de ambos os jogadores combinados.

Mas o problema é que levará dois décimos de segundo para que um dos jogadores veja a caixa reagir. As mensagens de ambos os jogadores levam 1/10 de segundo para chegar ao servidor e, em seguida, 1/10 de segundo para que os resultados do cálculo dos servidores sejam enviados aos dois jogadores.

Bottom line, jogabilidade atrasada.

E se a física for calculada apenas no cliente?

Suponha que tenhamos física calculada apenas no cliente. Vamos dar uma olhada no ponto de vista do jogador A. O jogador A bate na caixa e imediatamente começa a ir na direção deles. Uma mensagem também é enviada ao servidor informando o que o Jogador A fez.

Ao mesmo tempo, B fez o golpe e viu o caixote indo em sua direção e enviou uma mensagem ao servidor sobre o que eles fizeram.

2/10 de segundo depois, chega uma mensagem do servidor para os clientes. A é informado do que B fez, e B é informado do que A fez. O problema é que os dois clientes dizem: "Bem, o jogador X pode ter atingido esse ponto neste local, mas não há mais uma caixa nesse local, portanto o impacto não fez nada".

Resumindo, dois jogos estão fora de sincronia e os jogadores não têm uma experiência compartilhada. Qual é o sentido do multiplayer se ambos vêem coisas diferentes?

E se a física for calculada no cliente e no servidor?

Nesse caso, a física é calculada no cliente para que os jogadores vejam uma reação imediata sem atraso, mas também é calculada no servidor para que seja "correta" para todos os jogadores.

Ambos os jogadores acertam o engradado em suas respectivas direções e cada um vê o engradado se mover com base apenas no acerto. Mas, então, 2/10 de segundo depois, o servidor volta e diz: "Bem, na verdade, vocês dois estão errados. A caixa foi por esse caminho". De repente, ambos os jogadores vêem a caixa mudar drasticamente de direção e se mover para um novo local.

Bottom line é, um jogo glitchy.

Conclusão

Basicamente, não há como fazer um jogo de física perfeito com vários jogadores quando existe algum tipo de latência. Você pode fazer um jogo muito bom, mas sempre terá o risco de latência excessiva, criando uma experiência ruim para alguns jogadores. No entanto, existem coisas que você pode fazer para manter uma experiência de jogo agradável.

O que você pode fazer para que um jogo multiplayer corra bem

Use volumes de colisão simples. Não se preocupe em modelar todos os detalhes de uma forma com a física quando uma forma simples de cubo for adequada. Uma bola de espigão não precisa ser modelada como uma bola de espigão para a física. Em vez disso, apenas modele-o como uma esfera.

Crie pequenos objetos inconseqüentes itens somente para o cliente. Um exemplo pode ser pedaços de vidro quebrado de uma janela quebrada. Você pode permitir que cada cliente simule por conta própria, e isso realmente não importa se eles são diferentes.

Crie objetos físicos apenas se eles precisarem ser objetos físicos para manter baixo o número de objetos físicos ativos.

Execute seu jogo em câmera lenta ao fazer física para vários jogadores. Pense em "tempo de bala", talvez. Jogos em câmera lenta compensam a latência e permitem que vários jogadores interajam com a física juntos.

Permita que os jogadores configurem uma situação de algum tipo juntos, e então, de alguma maneira, a física é simulada para ambos os jogadores e ambos assistem ao resultado de suas ações combinadas. Os jogadores não podem interferir com a sequência até que ela seja concluída.

Jogadores físicos separados para que eles não possam interferir um com o outro. Isso seria ótimo para um jogo como boliche ou sinuca, onde apenas um jogador de cada vez tem controle ou cada jogador tem sua própria "caixa de areia" (como uma pista de boliche).

Se você não pode vencê-los, junte-se a eles e faça com que o atraso na física faça parte do seu jogo. Imagine uma história sobre estar em um universo glitchy com leis de física violadas ou algo do tipo :)

Apêndice: Como os jogos de tiro lidam com isso

Os jogos de tiro lidam com isso não fazendo física excessivamente complexa. Eles usam efeitos colaterais do cliente para que os jogadores vejam as coisas rapidamente, mas o servidor faz a chamada final sobre o que aconteceu.

Imagine um cenário em que o jogador A atire no jogador B. Seu jogo de tiro típico fará algo assim ...

  1. A calculará localmente se eles acertarem B e, se parecer que houve um golpe, ele executa um efeito de "golpe" como uma baforada de sangue. Isso é feito do lado do cliente para que o jogador veja imediatamente uma reação à sua ação. Se você não fizer isso, o jogo parece lento.
  2. A também envia uma mensagem ao servidor dizendo: "Eu atirei nesse vetor"
  3. Quando o servidor recebe a mensagem, ele analisa onde a equipe de TI pensa que estão os jogadores e decide se o vetor de tiro de A atinge B.
  4. Se o servidor decide A hit B, decide que B é atingido e envia uma mensagem para os dois clientes dizendo o que aconteceu.
  5. Se o servidor decidir que A NÃO atingiu B, B está bem e A "falha". Pode parecer que A bateu ("Eu vi o sangue soprar!"), Mas são os servidores que eles perdem.

Então, como A miss B pode parecer que eles os atingiram? Porque B pode ter sido movido, mas A ainda não o viu porque o servidor ainda não enviou uma mensagem "B mudou-se para aqui" para o cliente.

A Valve tem uma boa descrição em seu site sobre isso. Consulte http://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Tim Holt
fonte
2
Isso é verdade em um servidor com uma boa conexão. Existem muitos casos em que a física em jogos multiplayer falha e tenho certeza de que há muitas experiências ruins em jogos Mod de Garry. No entanto, se houver latência, os problemas que descrevi existirão. Você não pode contornar o fato de que a física precisa ser calculada muito rapidamente para ser suave. E se você tiver latência, haverá um atraso. Atraso significa atraso.
Tim Holt
1
Você pode voltar e reler minha postagem. Menos algumas opiniões no front-end da minha parte, estou descrevendo exatamente o que acontece em uma simulação de física com vários jogadores - incluindo as sessões de jogo do Garry's Mod. Você não pode contornar os fatos.
Tim Holt
2
Ok, eu mudei meu voto negativo para um voto positivo. Mas você pinta uma imagem realmente negativa para jogos multiplayer com a física, quando ela realmente foi feita antes e relativamente livre de falhas.
AttackingHobo
7
@ AttackingHobo: "Sem falhas" é relativo. Tendo trabalhado em um jogo com boa previsão de rede, agora vejo falhas onde não havia antes. Eles raramente afetam significativamente a mecânica, mas estão presentes. O ponto principal da previsão é que uma pequena imprecisão em tempo real é melhor que a precisão atrasada; isso não muda o fato de você estar sempre impreciso.
1
+1 em "Imagine uma história sobre estar em um universo glitchy com leis de física violadas ou algo assim".
Patryk Czachurski
13

Eu escrevi uma série de artigos sobre o tópico aqui: http://www.gabrielgambetta.com/fpm1.html

Os três primeiros artigos tratam de uma introdução ao tópico, previsão do lado do cliente, reconciliação do servidor e interpolação de entidade (esta é a parte que responde à sua pergunta específica). O quarto artigo (em breve) tratará de "coisas de filmagem" :)

A resposta de Tim Holt é praticamente isso. Meus artigos têm alguns diagramas que podem ajudá-lo a entender o que está acontecendo, mas Tim e eu estamos basicamente dizendo a mesma coisa.

ggambett
fonte
Good stuff ggambett!
Tim Holt
2
Muitos jogadores não entendem como essas coisas funcionam, mas é muito importante entender o eterno "WTF POR QUE EU PERDEI?" questão.
Tim Holt
Ou "por que meu personagem está vinculado a essa coluna com um elástico gigante?" em uma conexão caiu :)
ggambett
O Wiki da Valve tem um artigo que também aborda esses problemas. A página está em developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
Tim Holt
1
Eu amo a demonstração ao vivo. Que ótima maneira de visualizar o que está acontecendo.
Richard Marskell - Drackir
2

Não é irracional fazer previsões completas em seu próprio personagem para capacidade de resposta e deixar outros personagens ficarem atrás em 100ms para obter consistência. Se isso parecer ruim, considere ter seu próprio personagem um pouco atrasado para mantê-lo sincronizado. De qualquer forma, você ainda precisará de mecanismos de correção para suavizar previsões incorretas no caso de picos de atraso, e esse sistema lidará com situações como a que você descreve. Não importa se a latência é 100ms ou 1ms - seu cliente está sempre "atrasado" em algum sentido e, portanto, sempre tem que agir como se estivesse lidando com dados antigos e aplicar efeitos cosméticos, como interpolação, para torná-la razoável.

Kylotan
fonte
0

No final, tudo se resume a se contentar com os recursos de rede disponíveis. Idealmente, viveríamos em um mundo com latência zero e tudo pode ser perfeitamente sincronizado. Realisticamente, você atualiza os clientes a cada 100, 200, 300 ms e é necessário que haja uma lógica no cliente para tornar o que aconteceu mais tranquilo. A "suavidade" é muito importante; no final, o jogo só precisa se sentir suave, mesmo que no final haja alguma sincronização caótica entre o cliente e o servidor.

Uma boa postagem e uma melhor resposta podem ser encontradas:

Como escrever um jogo em rede?

DeusAduro
fonte
0

O problema não é realmente a latência. Pode ser compensado e previsto muito bem para esconder os problemas causados. A perda de pacotes também não é um problema - o sistema de rede deve ser escrito para ser robusto e tolerável à perda de pacotes. No entanto, o problema são os picos de latência e a latência imprevisível. Pacotes chegando fora de sincronia, alguns deles sendo descartados apenas devido a variações de latência, incapacidade de prever e interpolar por causa de variações de latência etc.


fonte