Física não sincronizando corretamente na rede ao usar o Bullet

11

Estou tentando implementar um sistema físico de cliente / servidor usando o Bullet, mas estou tendo problemas para sincronizar as coisas.

Eu implementei um estado de movimento personalizado que lê e grava a transformação dos meus objetos de jogo e funciona localmente, mas tentei duas abordagens diferentes para jogos em rede:

  1. Objetos dinâmicos no cliente que também estão no servidor (por exemplo, detritos não aleatórios e outras coisas sem importância) são tornados cinemáticos. Isso funciona corretamente, mas os objetos não se movem muito bem
  2. Os objetos são dinâmicos nos dois, mas após cada mensagem do servidor que o objeto foi movido, defino a velocidade linear e angular para os valores do servidor e chamo btRigidBody :: continueToTransform com a transformação no servidor. Também chamo btCollisionObject :: enable (true); para forçar a atualização do objeto.

Minha intenção com o método 2 era basicamente fazer o método 1, mas seqüestrar o Bullet para fazer a previsão de um pobre, em vez de fazer o meu para suavizar o método 1, mas isso não parece funcionar (por razões que não são 100% claras para eu mesmo percorrendo Bullet) e os objetos às vezes acabam em lugares diferentes.

Estou indo na direção certa? O Bullet parece ter seu próprio código de interpolação embutido. Isso pode me ajudar a melhorar o método 1? Ou meu código do método 2 não está funcionando porque estou acidentalmente pisando nisso?

EDIT: Outro problema com o método 1 que acabei de notar é que a resposta à colisão estará muito longe de colisões contra objetos não sincronizados. Os corpos cinéticos meio que disparam coisas até o infinito às vezes, uma vez que não podem ser repelidos.

Lucas
fonte
Algumas coisas que podem ajudá-lo a obter uma resposta: Qual idioma / mecanismo você está usando? Que tipo de conexão é essa? Quão ruim é o déficit de sincronização, comparado ao ping no servidor?
Fibericon 10/09/12
2
A segunda opção não funciona porque você define as velocidades para os valores do servidor somente após alguns quadros; portanto, entre cada pacote, existem alguns quadros em que as coisas podem mudar. Eu recomendaria a leitura de todas as postagens de Gaffer sobre física de jogos, você provavelmente deve ler primeiro 'fix your timestep', mas aqui está o artigo final que fala sobre física em rede gafferongames.com/game-physics/networked-physics
Roy T.
Estou usando um mecanismo de auto-desenvolvimento em C ++. No entanto, tenho certeza de que o déficit de sincronização não é tão ruim, provavelmente um quadro sobre o ping, se eu tivesse que adivinhar, mas ainda estou testando apenas a LAN. Vou dar uma olhada nesses artigos e sim, você tem razão em que as velocidades estão desativadas. No entanto, as coisas estão muito longe, como se a caixa estivesse do outro lado do mapa. A configuração explícita da transformação não deve tornar as coisas geralmente conformes? (mesmo se não é bonito ainda, jiggles, etc.)
Lucas
Eu li o post de Gaffer e era informativo, mas parecia lidar principalmente com o movimento dos jogadores, algo que eu já tenho trabalhando. Eu tenho lido e parece que meu código do método 2 é praticamente idêntico ao método usado no mecanismo Unreal . Eles não fornecem muitos detalhes, mas me faz pensar se a ideia é boa, mas meu uso do Bullet está incorreto.
Lucas
Uma leitura interessante, parcialmente relacionada ao seu tópico: gamasutra.com/view/feature/3094/… . É sobre um rts e não é sobre física, mas eles chegam ao ponto em que precisam sincronizar uma simulação no servidor e nos clientes. O jeito que eles fazem isso? Eles executar simulações independentes no cliente e no servidor, mas o servidor envia envia pacotes que certifique-se, que a simulação cliente não divergem e for corrigido, se não acontecer ...
Tom van verde

Respostas:

4

Você precisa de uma previsão adequada do lado do cliente .

Você realmente deve ler em detalhes o link que Roy T. forneceu em seu comentário . Ele descreve o que fazer com a entrada do jogador e a física dos personagens, mas o princípio permanece o mesmo para a "física orientada ao servidor".

Isso não é trivial de implementar, mas em poucas palavras, para objetos de jogo que precisam estar sincronizados:

  • Execute a física no servidor e no cliente;
  • O servidor envia atualizações regularmente;
  • O cliente reajusta continuamente e sem problemas o mundo da física com os valores do servidor.

Então, sim, você está caminhando na direção certa com o seu método 2. Porém, apenas sobrescrever os valores, você obterá saltos no cliente, o que você precisa fazer é interpolar de forma suave e contínua com os valores do servidor.

Para o seu bug atual, eu não estou familiarizado com o Bullet, mas você provavelmente está perdendo alguns valores, por exemplo, você definiu as velocidades linear e angular, mas definiu as acelerações?

Laurent Couvidou
fonte
Obrigado! Isso me faz sentir melhor por estar no caminho certo. Vou revisar meu código agora com um pente fino. Talvez alguma notificação não esteja sendo acionada ou, como você diz, estou perdendo um valor, já que o método 2 deve funcionar (espasmódico).
Lucas
3

O que eu faço pessoalmente é quem está hospedando o jogo, cria o mundo phsyics e sincroniza objetos com os clientes. Mesmo que seja um esquema de rede p2p, ainda baseio o mecanismo de física em um dos clientes dos jogadores.

Outra física que uso puramente como colírio para os olhos nem precisa ser sincronizada.

Em um protótipo que criei um tempo atrás chamado "boilerzerker", executei a física no host e os efeitos das partículas (também usando a física) não foram sincronizados em uma rede, mas independentes para cada cliente, porque eram agradáveis ​​para os olhos.

tsturzl
fonte
Obrigado, sim, essa é uma maneira de fazer isso. No entanto, isso não resulta em boas respostas de colisão no cliente para as coisas que o cliente faz e também as coisas doces para os olhos nem sempre interagem corretamente, uma vez que não podem ser repassadas às coisas do servidor (pelo menos nesse intervalo de tempo). Eu sinto que isso deve ser possível, já que motores como Unreal e Source parecem fazê-lo.
Lucas
o colírio para os olhos não precisa ser sincronizado, pode ser calculado por cliente. a resposta no cliente é calculada no servidor, as coordenadas do cliente são calculadas e enviadas de volta, você não envia um retorno de chamada ao cliente dizendo que ele colidiu, o que provavelmente pareceria horrível.
tsturzl 19/09/12
2

É impossível implementar mundos de física síncrona em rede. Pequena diferença no passo N, diferença muito maior no passo N + 1 Você não pode aplicar forças ou impulsos para mantê-lo sincronizado e parecer realista.

Soluções: -

  1. Você pode sincronizar apenas alguns objetos, como personagens ou carros de corrida, especialmente se eles forem cinemáticos. Mas a maior parte do mundo não estaria sincronizada para parecer realista.

  2. Você pode ter mundos físicos no servidor e transmitir posições e velocidades de objetos para clientes.

Máx.
fonte
Você pode tentar jogar algum jogo de rede com a física para ver que os mundos não estão sincronizados. Por exemplo, o Need For Speed ​​World é gratuito e possui vários jogadores e física básica. (caixas na estrada e objetos destrutíveis)
Max
Não tenho certeza de segui-lo exatamente. Tenho certeza de que isso é possível, pois muitos jogos permitem que os jogadores joguem caixas (por exemplo). Parece que a sua opção 2 é semelhante à minha opção 2, mas não consigo fazer com que o Bullet encaixe os objetos corretamente nas posições dos servidores. Talvez esse seja o meu problema de raiz?
Lucas
1
Não. Geralmente é ilusão de síncrono. Se você comparar telas, verá que, quando salta nas caixas, as caixas voam em direções diferentes. ou caixas não são nada de física (apenas animações editadas). O número de caixas é diferente. Quando digo animação, quero dizer que não há animação física por trás dos movimentos. Eles não fazem vários truques para fazer a imagem parecer um tanto sincronizada, mas não são mundos da física síncrona. Você deve procurar e comparar como eles se movem em jogos diferentes.
Max