O que enviar para o servidor em tempo real no jogo FPS?

23

Qual é a maneira correta de informar a posição do nosso player local no servidor? Alguns documentos dizem que é melhor enviar as entradas sempre que elas forem produzidas. E alguns documentos dizem que o cliente envia sua posição em um intervalo fixo.

Com a abordagem de envio de entradas: O que devo fazer se o jogador estiver pressionando as teclas de direção? Isso significa que eu preciso enviar um pacote para o servidor em todos os quadros. Não é demais? E há também a rotação do jogador a partir da entrada do mouse. Aqui está um exemplo:

http://www.gabrielgambetta.com/fpm_live.html

Que tal enviar a posição na abordagem por intervalo fixo. Ele envia muito poucas mensagens para o servidor. Mas também reduz a capacidade de resposta.

Então, qual caminho é melhor?

syloc
fonte

Respostas:

19

Resposta simples: trapaceie ou não seja tão preciso!

Se você já jogou algum jogo de tiro online, provavelmente já experimentou o chamado "elástico" se a sua conexão com o servidor estiver ruim.

Isso é causado pelo fato de seu cliente corrigir sua posição periodicamente.

Basicamente, o que acontece nos dois lados:

  • O servidor rastreará seu movimento e enviará atualizações aos clientes conforme o esperado. Essas nem sempre precisam ser atualizações completas. A cada x quadros, pode haver uma atualização completa; em todos os outros quadros, você envia apenas novos vetores de velocidade (se houver alguma alteração).

  • Seu próprio cliente permitirá que você se mova livremente, mas usará as atualizações fornecidas pelo servidor para corrigir / ajustar sua posição. Isso garantirá que o jogo seja responsivo, mesmo que você não atualize a posição quadro a quadro.

Mas como a entrada é tratada? Seu cliente enviará sua posição ao servidor "Eu mudei para lá". O servidor verificará esta atualização (por exemplo, você poderá se mudar para lá tão rápido?) E se for válido, moverá você (ou rejeitará sua atualização, resultando em "faixas de borracha").

Portanto, sim, sua abordagem de intervalo fixo provavelmente funcionará e será suficiente.

Mas mesmo se você quiser enviar informações e manipular os movimentos de ambos os lados, lembre-se de que não precisa enviar "o botão ainda está pressionado". Em vez disso, envie um evento quando o botão for pressionado e outro quando o botão for liberado.

Mario
fonte
5
Sim, eu posso acompanhar a pressão e liberação do botão. Mas e quanto à entrada do mouse? Está mudando constantemente.
syloc
6
"Em vez disso, envie um evento quando o botão for pressionado e outro quando o botão for liberado." - É verdade, mas é necessário que haja verificações para garantir que o evento "no lançamento" seja eventualmente forçado, dependendo das regras dos jogos. Por exemplo, no multijogador Rainbow Six Vegas 2 , um jogador pode começar a disparar sua arma e um bug (infelizmente comum) faz com que a mensagem "pare de disparar" não chegue ao servidor com êxito. Isso faz com que o áudio do tiro permaneça em um loop infinito pelo resto da partida. Apenas um exemplo para ter cuidado. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: Apenas lide com o lado do cliente e deixe o servidor determinar se o movimento é válido / possível (para evitar coisas como teleport hacks e similares).
Mario
@syloc Basta definir um intervalo para o mouse, mas para economizar largura de banda extra, faça uma verificação no lado do cliente para ver se ele foi alterado. Se houver um período sem movimento do mouse, você não precisará continuar enviando mensagens sobre o assunto.
Agweber
Em um dos meus trabalhos, tivemos um engenheiro praticamente louco, otimizando o comportamento da mola para atualizações de posições perdidas para discagem (há 13 anos). Agora vejo jogos com muita largura de banda e latência ridiculamente baixa sofrendo com esse problema, parece que o problema nunca está longe ou que as pessoas se preocupam muito menos com isso atualmente.
Andon M. Coleman
5

Se você ainda não o fez, sugiro que você leia estes dois artigos profundos, mas compreensíveis: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking e http://fabiensanglard.net/quake3/network.php .

Isso explica por que é recomendável usar o envio de pacotes com 'intervalo fixo'. Para ser breve, é de fato principalmente importante para pacotes enviados pelo servidor.

O envio de um pacote tem um custo fixo e o tamanho máximo de um pacote de rede é de cerca de 1,5 KB. Portanto, se você tiver, por exemplo, 16 jogadores em seu servidor, cada quadro ao calcular o movimento de um jogador, um código ingênuo poderá enviar um pacote de atualização para cada jogador após cada resolução de movimento, então 16 * 16 = 256 pacotes. Se você tem uma taxa de quadros de 30, são 7680 pacotes.

Uma abordagem melhor é criar um buffer em cada início do quadro, concatenar suas 16 posições calculadas atualizadas e enviá-las aos seus 16 jogadores.

Agora você envia apenas 480 pacotes por segundos para os mesmos resultados.

No caso de jogador para servidor, isso significa apenas que você deve enviar, no mesmo pacote, o máximo de dados, como; olhou posição, ações chamado esse quadro e assim por diante.

Sobre a segunda parte da sua pergunta - a maneira como escolhi reduzir a sensação de atraso foi enviar essas informações ao servidor em cada quadro:

  • posição atual real do jogador (usada pelo servidor para verificar se as posições do lado do servidor e do lado do jogador não estão muito dessincronizadas).

  • Posição estimada do jogador em 1 segundo: calculado pelo cliente: se o jogador não mudar a direção do mouse e deixar o teclado em seu estado atual por 1 segundo, onde estará o jogador? (não nos importamos com colisões) Se o jogador não estiver se movendo, sua posição estimada em 1 segundo é a atual.

  • A posição que ele olha.

Cada vez que o servidor recebe essas informações, ele atualiza a posição futura e a posição visualizada, e a entidade do jogador eventualmente se move em direção à sua posição futura.

Os jogadores nunca são exatamente sincronizados, mas a resposta de entrada é instantânea (o mais importante para mim) e eu achei que as posições previstas eram precisas o suficiente para mim.

GaelFG
fonte
"Os jogadores nunca são exatamente sincronizados" . Acho que também é importante mencionar que o nível de precisão aqui depende do jogo (jogo) real. Por exemplo, um MMO clássico em que você apenas clica e seleciona entidades, não precisará de precisão perfeita para praticamente tudo, mas em um jogo de tiro, a sincronização boa a perfeita é essencial.
Mario
O fato é que ninguém em sã consciência usa o TCP para um FPS. Eles preferem lidar com re-seqüenciamento complicado e datagramas perdidos do que incorrer na sobrecarga do TCP.
Andon M. Coleman