Rede e movimento na UNIDADE do MMORPG

8

Estou programando um servidor dedicado em c # usando DLLs do BeamServer2. No começo, eu queria poder ver outros jogadores se mexendo no nosso mapa Omuni já criado. Fiz isso enviando sua posição ao servidor em cada quadro. Isso deu certo e eu pude brincar com alguns amigos, mas o movimento não foi isento de problemas. Então, comecei a tentar adicionar suavização de movimento e também alguma segurança para que eles não pudessem simplesmente enviar uma posição falsa ao servidor sem que o servidor o impedisse de alcançar outros clientes.

O que eu fiz foi criar um masterClient que possui um motionController no remotePlayer. Quando um cliente quer se mover, ele se move localmente e envia uma mensagem ao servidor com sua direção para se mover. O servidor pega a velocidade e envia para o masterClient. O masterClient que move o remotePlayer da mesma forma que o remotePlayer se move. Quando ele para de se mover, ele envia uma mensagem com sua posição. O masterclient que verifica se a posição que ele chegou é tão próxima quanto a posição que ele tem do cliente, se é realista de acordo com o ping do cliente que o servidor o coloca na posição do cliente.

Isso funciona, mas ainda tenho um problema de atraso e não tenho certeza de como corrigir isso. Devo suavizar o movimento do cliente, mas descobri que posso apenas lerp (x / 2, y / 2, z / 2) para a posição e colocá-lo na posição real no próximo quadro; falhei nisso e tentará novamente em breve. Mesmo se isso for adicionado, não tenho certeza se o lagg foi corrigido.

Quaisquer outras técnicas, sugestões, perguntas, ...? Obrigado, Diede.

Diede
fonte

Respostas:

8

Existem muitos problemas / tarefas envolvidos na programação de jogos de rede em tempo real "sem atraso".

  • velocidade do hardware (energia da CPU necessária para o cliente e o servidor)
  • distância e equipamento da rede (conexão LAN ou WAN?)
  • largura de banda do servidor (quantos jogadores)

Em segundo lugar, você tem os "bandidos" que sempre tentam trapacear nos jogos. Se o seu jogo for aberto, considere o que aconteceria se eu me sentasse e injetasse pacotes de rede "falsos". Considere se alguém postou "posições inacessíveis" ou "saúde / munição".

Minha sugestão para sua arquitetura, para começar, seria algo como isto:

  • Servidor, controla todos os dados vitais, calcula E valida o movimento.
  • Cliente, recebe dados sobre o que mostrar na tela + alguns dados "pense no futuro" sobre objetos em movimento.

A maioria dos FPSs em tempo real, como eu sei, faz algum tipo de "nós sabemos que você está seguindo essa direção nessa velocidade, então apenas simulamos isso até obtermos outros detalhes do servidor"

Portanto, seu cliente deve postar "o que ele solicita" e pode até começar a se mover nessa direção, mas pode ser "forçado a voltar" pelo servidor se o servidor rejeitar o movimento. Aqui você deve pensar: e se o cliente postar "falsos cordões" fora do mapa ou de repente "pular". O servidor precisa rastrear se a nova posição é possível a partir do ponto anterior OU o servidor recebe apenas a mensagem que diz: "CLIENT MOVE FORWARD 200" e, em seguida, o servidor processa o que isso fará de acordo com os dados do mapa e do jogo.

Isso causará algum atraso, mas, novamente, se você permitir que o cliente receba esses dados e faça algumas contas, ele não precisará de uma atualização a cada ms / quadro, poderá ficar um pouco sem o atraso perceptível na tela.

Talvez você possa até dividir o mapa em "blocos virtuais" (se for um jogo de vetores) para ter uma maneira rápida de calcular onde os objetos devem ser os próximos.

World of Warcraft / Campo de batalha / Contra-ataque

Acredito que o WOW também esteja fazendo isso dessa maneira. Você pressiona uma tecla, o servidor recebe seu movimento "desejo" e responde com "você está se movendo agora" e, em seguida, o cliente mostra isso + o servidor simula a nova posição no servidor em algum tipo de "sessão por cliente". É aqui que a "quantidade máxima de jogadores por jogo" está ficando desagradável, porque seu servidor precisa acompanhar todos e basicamente fazer isso como "baseado em turnos" - mas tão rápido que parece em tempo real.

Assim...

Foreach (Client in GameSessionList)
{
   ParseInput();
   ParseMovement(); // including collission test
   ResponseSend(); // new positions+movement data for client and objects/other players
}
BerggreenDK
fonte
3
Independentemente do mérito de sua resposta, há alguma razão para ser rude?
Konrad
Fiquei com a impressão de que, na maioria dos jogos de FPS, os clientes e o servidor colidem independentemente, e o servidor corrige os clientes se eles variarem muito, em vez de apenas os clientes simularem.
Magus
Não sei como todos os FPS fazem isso. Mas sim, por exemplo. a série BF tem algo que eles chamam de Netcode, o que significa que eles executam os cálculos localmente e enviam os resultados ao servidor que, em seguida, verifica e distribui os resultados (como foi o que me disseram). Isso pode ter a ver com a enorme quantidade de "partículas" / detalhes que precisam ser transferidos de outra forma. Onde WOW é um mundo mais estático e você não tem colisão entre os personagens (no modo normal), então não há problema em deixar você "deslizar" por outra pessoa.
precisa
2

A parte desafiadora da compensação de atraso é que você receberá atualizações de clientes que estão fora de serviço. O comando de um cliente atrasado enviado no momento T pode muito bem chegar após um comando do cliente não atrasado enviado em T + 40ms. A aplicação dos comandos na ordem em que você os obtém levará a todos os tipos de maldade. Fazê-lo corretamente, por outro lado, envolve retornar o tempo e reproduzir todos os comandos que foram emitidos desde então.

Não há uma maneira fácil de contornar isso, mas existem várias soluções válidas. Você pode encontrar um relativamente fácil descrito aqui .

Há muita pesquisa nesse campo, dê uma olhada!

drxzcl
fonte
1

Eu criaria o cliente como se fosse um jogo sem rede. Ou seja, qualquer coisa que você faça é imida ao cliente. Em seguida, adicione, paralelamente a isso, seu código de rede. Este código obterá os dados do movimento. Simples a partir de cabos, direção e velocidade. Apenas envia isso para o servidor que valida. O servidor envia uma posição ok ou nova.

Então você tem todo o código do cliente em execução, como se estivesse sozinho no mundo. Em seguida, apenas recebe novos dados de correção do servidor ou um ok. Se você pressionar e segurar por dez segundos, o servidor apenas receberá esses dados. Você pode considerar o envio / recebimento de dados a cada segundo, mesmo que esteja apenas pressionando o botão Avançar, caso contrário, se você atingir um pico de atraso, poderá executar para sempre.

Espen
fonte