Estou implementando um servidor de jogo que suporta corpo a corpo do Star Control . Então você tem naves voando e atirando, com física super simples de velocidade / aceleração / amortecimento para impulsionar o movimento.
Li Valve, Gafferon e Gambetta e implementei o algoritmo de Gambetta para previsão de clientes:
A previsão do cliente funciona no navio do jogador, atualizando sua posição a partir do servidor e reaplicando a entrada ainda não processada pelo servidor ao navio do jogador.
Infelizmente, não funciona bem para o meu jogo. Acredito que tenha a ver com o fato de que o exemplo de Gambetta não leva em conta objetos que já estão em movimento ou comandos que são atualizados passo a passo. (por "passo" quero dizer quadro). Portanto, no meu jogo, o jogador pressiona para acelerar a nave (que já está se movendo), que continua se movendo no cliente, envia o comando ao servidor e geralmente recebe o instantâneo mundial do servidor na próxima etapa. Eu recebo algo mais como:
O comando player é executado na etapa 3 do cliente , mas no servidor é executado apenas na etapa 5 do servidor . No momento em que o instantâneo mundial é recebido pelo cliente na etapa 6 do cliente , a previsão está muito distante, especialmente em velocidades mais rápidas.
O ponto crucial do problema é que o cliente executa o comando na etapa 5 , mas o servidor executa na etapa 6 . Pensei em talvez enviar a etapa do cliente com o comando e fazer com que o servidor reverta e execute novamente o comando com a etapa de tempo do cliente. Isso pode levar a uma série de outros problemas - como o que acontece com os comandos recebidos desde a reversão ou como os clientes trapaceiros podem explorar, alterando a etapa enviada.
Ler e assistir a vídeos como este no Google menciona uma abordagem diferente, na qual você muda gradualmente a posição do jogador para corresponder à do instantâneo em algumas etapas.
Minhas perguntas:
Você pode fazer o algoritmo de Gambetta funcionar com movimentos constantes de passos? Ou é conceitualmente incompatível com o meu jogo?
A interpolação gradual em etapas é o caminho correto a seguir? Nesse caso, como você interpola um objeto já em movimento da posição do cliente para corresponder ao que acabou de ser recebido do servidor?
Esses métodos, a interpolação gradual e o algoritmo de Gambetta podem funcionar em conjunto, ou são mutuamente exclusivos?
Respostas:
Durante os 6 meses desde que fiz essa pergunta, acabei desenvolvendo um servidor de jogos de código aberto completo para lidar com esse problema exato (e muitos outros!): Http://lance.gg
O P&D envolvido agora me permite responder minhas próprias perguntas:
Você pode fazer o algoritmo de Gambetta funcionar com movimentos constantes de passos? Ou é conceitualmente incompatível com o meu jogo?
O algoritmo de Gambetta não funcionará quando o movimento da entidade não for determinístico (do ponto de vista do cliente). Se uma entidade pode ser afetada sem a participação da física ou de outros atores, por exemplo, é necessário adotar uma abordagem mais elaborada.
A interpolação gradual em etapas é o caminho correto a seguir? Nesse caso, como você interpola um objeto já em movimento da posição do cliente para corresponder ao que acabou de ser recebido do servidor?
Isso aborda um tópico diferente, que é a reconciliação do cliente das atualizações do servidor. A interpolação gradual funciona, mas para jogos de ritmo muito rápido, como o da pergunta, é melhor implementar a extrapolação
Esses métodos, a interpolação gradual e o algoritmo de Gambetta podem funcionar em conjunto, ou são mutuamente exclusivos?
Eles podem trabalhar juntos, mas somente se o movimento da entidade for determinístico do POV do cliente. Portanto, não funcionará se a entidade for afetada pela física ou psuedo-física, como inserção, arraste etc.
fonte
Seu jogo parece ser "em tempo real" demais para pensar em termos de etapas do tempo. Eu só pensaria em termos de "turnos" se o jogo pudesse ser considerado "baseado em turnos". Caso contrário, apenas abandone a ideia de voltas ou etapas. Tudo fica mais fácil, então :)
Observe que você prevê localmente para o seu player e interpola apenas para outras entidades (conforme explicado no terceiro artigo da série). A maneira de lidar com as atualizações do servidor para objetos que já estavam em movimento é a reconciliação do servidor, explicada na metade inferior do 2º artigo (aquele ao qual você vinculou).
Espero que isto ajude :)
fonte