Sei que minha configuração multiplayer super simples provavelmente não é uma boa ideia, mas por quê?

11

Estou criando um MOBA simples e apenas por diversão. Eu estava criando tudo como single player e então percebi "ah, merda, eu provavelmente deveria adicionar o multiplayer, hein".

Eu nunca fiz nada com redes antes, então aprender como integrar o Lidgren no meu jogo foi divertido e incrível. O problema é que eu sei muito bem como as coisas estão fazendo errado, porque não é suficientemente robusto para os jogos tradicionais, tanto quanto eu sei, mas o que há de errado nisso?

O que estou fazendo é, basicamente, sempre que um jogador faz uma ação, ele envia uma mensagem ao servidor dizendo "ei, eu fiz isso". O servidor e o cliente estão executando a mesma simulação. O servidor envia uma mensagem para todos os outros clientes, informando que aquele cara fez aquilo.

Na maioria das vezes, exceto em alguns casos, quando um jogador faz alguma coisa, o cliente assume que é legal e segue adiante sozinho. Então, quando você clique com o botão direito em algum lugar se mudar para lá, o cliente do jogador apenas começa a se mover a sua cara lá, e , em seguida, envia uma mensagem para o servidor dizendo a ele sobre isso.

Então, basicamente:

  • O jogador 1 lança um feitiço para fazê-lo se mover 100% mais rápido por seis segundos
  • O cliente local do jogador 1 adiciona esse buff ao objeto Unit
  • O cliente do jogador 1 envia uma mensagem ao servidor dizendo "ei, acabei de lançar este feitiço"
  • O servidor garante que ele realmente tenha mana suficiente para lançar esse feitiço e, nesse caso, adiciona esse buff à cópia do servidor desse objeto Unit
  • O servidor envia uma mensagem para todos os outros clientes dizendo "ei, esse cara acabou de lançar esse feitiço"
  • Todos os outros clientes recebem a mensagem e dizem "ah, tudo bem, legal" e adicionam esse bônus ao objeto de unidade local desse jogador

Venho examinando as coisas para ver como os grandes jogos são multijogadores, e é meio confuso para alguém que está começando a se interessar por essas coisas, mas parece que o mecanismo Source envia um pacote contendo todas as alterações para tudo no jogo. mundo todo carrapato? Novamente, totalmente novo para essas coisas, mas você pode realmente enviar tantos dados com tanta frequência?

Desculpe se isso é um pouco desmedido, mas basicamente, eu estava me perguntando por que meu sistema mais simples não é o caminho certo a seguir, porque, se fosse, outros jogos o usariam, certo?

takua108
fonte
6
Uma etapa que você está perdendo é que o servidor também envia essa mensagem ao cliente original (não apenas a todos os outros) para confirmar ou negar o resultado da simulação; o cliente de origem continua indo ou se ajustando à nova realidade. Fora isso, esse método é bom e as outras respostas abaixo ajudarão você a entender melhor outros aspectos.
Patrick Hughes
1
O mais impressionante é que o restante de nós tem uma esperança razoável de que a rede não seja tão difícil. É factível.
ashes999

Respostas:

12

Além da resposta do Byte56, há mais algumas coisas a considerar:

Como você vai se comunicar entre os clientes sobre o movimento dos jogadores? Ao contrário da maioria das ações de outros jogadores, que tendem a ser eventos isolados e provavelmente pouco frequentes, o movimento é contínuo. Há um limite para a taxa na qual você pode (e deseja, nesse caso) enviar e receber atualizações. A previsão do lado do cliente mencionada pelo Byte56 geralmente envolve atualizações periódicas sobre a posição e a velocidade do cliente. O cliente interpola localmente entre eles, usando algo como um spline cúbico .

Um segundo problema, que se conecta aos anteriores, é que o UDP não tem entrega garantida. Você não pode ter certeza de que todas as mensagens enviadas chegam ou chegam na ordem correta. Você pode enviar os pacotes 1, 2 e 3, e o servidor recebe 3, depois 1 e não 2. Freqüentemente, eles estarão na ordem certa, e frequentemente chegarão, mas nem sempre. Portanto, você precisa de um sistema robusto para a perda de pacotes. Um sistema simples de confirmação é suficiente. Normalmente usado é um campo de bits informando ao outro nó se ele recebeu as últimas 32 mensagens (para um int de 32 bits) e qual foi a última mensagem recebida. Dessa forma, você pode rotular as mensagens como críticas ou não e reenviar se elas não receberem críticas. Há uma discussão bastante decente sobre isso aqui .

Você também deve ter em mente, ao fazer isso, que seus clientes estarão fora de sincronia entre si. Cada um mostrará os outros players interpolando entre os dois quadros de rede anteriores enquanto você trabalha no próximo, no melhor cenário. Portanto, você precisa de um sistema que leve em consideração (razoavelmente) que o que um jogador viu quando ele executou uma ação não era o estado real do jogo quando ele fez essa ação. Ele estava reagindo a um antigo estado de jogo fora de sincronia.

Finalmente, se este jogo se destina a ser competitivo, você também precisa se preocupar com trapaças. Assim, na medida do possível (e razoável), você deve desconfiar dos clientes e verificar se suas ações foram possíveis. "Não, você não pode atravessar aquela parede. Não, você não pode andar mais rápido que a velocidade da corrida. Não, você não pode afirmar que atingiu esse alvo." etc.

Para obter mais idéias, recomendo navegar nos outros artigos desse segundo link.

Boa sorte!

TASagent
fonte
6

O que você está descrevendo é essencialmente uma previsão do lado do cliente , mas você não diz o que acontece quando o servidor e o cliente discordam.

Ele evoluiu desde os dias em que o cliente era apenas um terminal burro, enviando sua entrada para o servidor, e o servidor informou ao cliente o resultado. No entanto, quando os jogos se moviam para além da LAN (e freqüentemente antes), a latência era perceptível nessa situação. O que você está descrevendo, a previsão do lado do cliente foi introduzida para corrigir isso. Agora, o cliente também simula o movimento enquanto aguarda a resposta do servidor. Então eles chegam a um acordo sobre o resultado. Com o servidor sendo a autoridade.

Os próximos passos são como você responde às divergências. Se você não tiver nada para isso, obterá o cliente com faixas de borracha ou tele-portabilidade quando o cliente e o servidor discordarem.

MichaelHouse
fonte
5

Cronometragem. As outras respostas não mencionam o tempo dos eventos no servidor e nos diferentes clientes. Dependendo do jogo, isso pode ser algo a se observar. A latência (também conhecida como Lag) introduz um atraso variável entre quando um pacote é enviado e quando é recebido. O tempo pode ser complicado, mas tentarei explicar os possíveis problemas da melhor maneira possível. Existem alguns jogos que podem sobreviver sem se preocupar com isso, mas aqui está um exemplo simples de onde isso pode causar problemas.

Suponha que todos atuem em pacotes assim que chegarem.

@ Time 0 (wall time), Player 1 puts up a shield   (Message has been sent, but not received by anyone)
@ Time 1, Player 2 shoots player 1   (Message has been sent, but not received by anyone)

Suponha que o Tempo 0 (T0) e T1 estejam próximos.

O que acontece a seguir depende de quem está olhando para isso e da ordem em que os pacotes chegam ao servidor. O servidor deve sempre ter a palavra final. Se o servidor receber os pacotes na ordem acima, o servidor aplicará o escudo antes do tiro e o jogador 1 (P1) sobreviverá. Da perspectiva de P1, tendo ele mesmo colocado o escudo, ele o verá antes do tiro e sobreviverá. Mas e o P2? Eles verão o tiro imediatamente porque o atiraram, mas verão o escudo primeiro? Se (T0 + latency between P1 and the server + the latency between the server and P2) > T1o escudo aparecer após o tiro, e P2 achará que o tiro matou P1. O servidor terá que corrigir essa situação de alguma forma.

Se, no entanto, o servidor receber os pacotes na ordem inversa (o que é bem possível, mesmo que T0 <T1), ocorre o contrário. P1 está errado (e morto), enquanto P2 está correto (e vitorioso).

Existem algumas maneiras de lidar com situações como essa, mas a mais fácil é deixar o servidor fazer tudo. Você pode tentar simular isso no cliente, mas não permita ações permanentes, como a morte. Os jogadores terão que esperar por importantes confirmações de mudança de jogo do servidor.

Enviar um registro de data e hora com ações pode ser benéfico. Se você confiar principalmente nos clientes, poderá usar esses carimbos de data / hora para determinar qual ação ocorreu primeiro, em vez de seguir nossa primeira suposição. Isso pode ser complicado, porque o recebimento de mensagens do passado geralmente significa que você precisa poder reverter o tempo.

O tempo é divertido, eh? Não importa o que você acaba fazendo, é útil estar ciente desses problemas de tempo.

John McDonald
fonte