Como lidar com computadores mais rápidos em um videogame em tempo real cliente / servidor

15

Estou criando meu primeiro jogo online usando o socket.io, e gostaria que fosse um jogo multiplayer em tempo real como agar.io ou diep.io.

Mas me deparei com a questão de tentar descobrir como fazer com que todos os computadores funcionem na mesma velocidade.

Eu tenho três ideias para modelos, mas nenhuma delas parece certa, e estou imaginando como os videogames normais fazem isso. (Você pode pular a leitura de minhas idéias; elas apenas te dão uma maneira de ver os problemas que estou tendo.)

  1. O servidor permite que os clientes sejam executados por conta própria e passem atualizações para o servidor, que os transmite para o restante dos clientes. Isso tem o problema de alguns computadores rodarem mais rápido do que outros, permitindo que eles se atualizem mais rapidamente e se movam pela tela mais rapidamente.

  2. O servidor informa aos clientes quando atualizar. Posso esperar até que o último cliente responda (uma idéia terrível no caso de uma pessoa ter um computador lento), espere até que o primeiro cliente responda (novamente, aguarde a comunicação antes de cada quadro) ou simplesmente envie-os o mais rápido possível parece ter o mesmo problema que o número 1).

  3. No início do jogo, peça ao servidor para informar aos clientes a rapidez com que atualizar. Isso significaria que o cliente seria responsável por restringir o movimento entre esse período de tempo. Por exemplo, se alguém conseguisse pressionar um botão duas vezes nesse período, ele só enviaria um evento de pressionamento de um botão. Isso tem o problema de que algumas ações seriam ignoradas (como o pressionamento de botão duplo) e que a interação dependeria do clock do cliente, que pode não corresponder ao clock do servidor. O servidor teria, então, que acompanhar cada cliente e garantir que as atualizações estivessem sendo enviadas no momento correto.

Eu já fiz algumas pesquisas para pesquisa de problemas , mas os artigos que li não parecem abordar especificamente o que fazer se um cliente envia atualizações mais rapidamente do que outros clientes.

No meu caso particular, estou lidando com pessoas que têm velocidades de teclado mais rápidas (o computador enviava mais atualizações de teclado do que outros computadores).

Como os programadores costumam lidar com isso?

    
por Pro Q 20.06.2016 / 18:13
fonte

3 respostas

8

Sua terceira ideia parece ser a mais próxima do que eu considero a solução do setor para esse tipo de problema.

O que você está descrevendo é comumente chamado de Ticks . Em cada tick, um número fixo de ações seria processado para cada cliente em série. Muitas vezes, os servidores de jogos terão algumas ações paralelas quando capazes, mas isso é um problema muito mais complicado.

Um tick provavelmente estará na forma de 1 / N segundos, N sendo o número de ticks por segundo ou Tickrate. Este tickrate pode ser muito frequentemente ou muito pouco frequente, dependendo do seu caso de uso. Minha sugestão pessoal seria evitar um tickrate acima de 60 ticks / segundo, a menos que você tenha certeza de que precisa de mais. Você provavelmente não:)

As ações devem ser atômicas. Por exemplo, em slither.io, uma ação como mover não deve processar imediatamente algo como quebrar sua corrente, a menos que o jogador que você acertou já tenha feito o movimento. Isso pode parecer trivial para algo no nível dos pixels, mas se você estiver lidando com o movimento baseado em blocos, isso se tornará muito mais óbvio e garantirá justiça. Se o Jogador A se mover para o bloco X, Y e o Jogador B estiver naquele bloco, você deve garantir que até o final do movimento, o jogador B ainda estará naquele bloco para quaisquer ações que ocorram entre eles.

Além disso, eu diria evitar ter qualquer um dos seus cálculos feitos no lado do cliente, a menos que sejam feitos independentemente no lado do servidor. Isso fica complicado e caro com a física (muitos jogos optam por uma menor taxa de variação física do que muitas outras ações e eventos por causa disso)

Para referência, aqui é um bom link para complementar o seu próprio entendimento sobre servidores de jogos e redes multiplayer.

Por último, eu diria que não deixe a justiça arruinar seu servidor. Se houver explorações que façam com que seu jogo seja injusto, corrija-as. Se é uma questão de um computador melhor ter uma ligeira vantagem, eu diria que pode não ser tão grande coisa.

    
por 20.06.2016 / 21:37
fonte
0

O sistema a seguir garante que todos os clientes e o servidor compartilhem quase o mesmo estado de jogo a qualquer momento.

Tenha o estado do jogo no cliente e no servidor.

Quando um cliente tenta usar um comando (mouse, teclado, etc.), observe seu estado do jogo, se ele for válido.

Se for, envie o comando para o servidor, sem executá-lo no cliente de envio.

Quando o servidor recebe o comando, observe seu estado do jogo, se ele for válido.

Se for, envie o comando de volta para TODOS os clientes com a data futura exata após o que deve ser concluído, sendo executado no servidor, em seguida, execute as ações solicitadas pelo comando após um atraso igual ao tempo mínimo para enviar o comando aos clientes. em seguida, registre a data, isso ajuda a fazer previsões futuras. Se o tempo variar demais, torne o seu sistema de jogo mais determinista.

Quando um cliente recebe um comando do servidor, examine seu estado do jogo, se for válido, execute imediatamente as ações solicitadas pelo comando, observe a data atual e compare-a com a previsão de data recebida. Se não for válido, o cliente está fora de sincronia. (Todos os clientes com uma conexão semelhante recebem ao mesmo tempo)

Se a data for anterior, você tem um problema na etapa anterior, corrija isso. Se a data é um pouco depois de fazer nada, Se a data é longa depois, o cliente está fora de sincronia, ou seja, o cliente fica muito atrás.

Quando um cliente está fora de sincronia, solicite uma cópia de todo o estado do jogo do servidor e use-o. Se isso acontecer com muita frequência, corrija isso porque é mais caro do que enviar comandos.

Nos clientes, renderize as coisas apenas na tela quando não houver mais nada a fazer. Em cenários simples, a função render usa apenas o estado atual do jogo como entrada.

Além disso, você pode otimizar muito, usando sistemas preditivos, agrupando comandos, renderizando apenas diffs, etc.

A validação deve ser diferente, por exemplo, cabe ao servidor limitar as requisições de comando / unidade de tempo.

    
por 21.06.2016 / 05:37
fonte
0

Eu não sei se isso é problema de bibliotecas ou ambiente que você está usando, mas eu acho que você está se aproximando totalmente errado.

Na grande maioria dos jogos multiplayer, é apenas o servidor que está fazendo cálculos reais. Os clientes são apenas máquinas IO mudas, onde apenas o problema de desempenho real é desenhar gráficos 3D. E nesse caso, não importa se o cliente pode rodar a 20 ou 200 FPS, porque isso afeta apenas visuais. Isso significa que "atualização do cliente" não tem absolutamente nenhum significado. O cliente pode tentar "prever" o que o servidor pode calcular, mas isso é apenas para suavizar a sensação de jogabilidade e não tem impacto real no próprio jogo.

faster keyboard speeds

Eu nem sei o que isso significa. A maioria das pessoas não consegue nem acompanhar a velocidade dos teclados low-end, então como isso afetaria o desempenho dos jogadores?

Caso contrário, a questão parece muito ampla e você deve se concentrar em um único problema real, em vez de tentar criar um problema "geral" que talvez nem tenha.

    
por 21.06.2016 / 07:44
fonte