Eu li Valve + Gafferon e centenas de páginas do Google, mas, por qualquer motivo, não consigo entender a previsão do cliente.
Para meu entendimento, o problema básico é:
- O cliente A envia entrada em
T0
- O servidor recebe entrada em
T1
- Todos os clientes recebem a alteração em
T2
No T2
entanto, usando a previsão do cliente, o Cliente A agora está em uma posição apropriada para T4
.
Como você garante que o Cliente A, ao prever que o servidor aceitará a solicitação de movimentação, não esteja à frente do servidor? Obviamente, sempre que estão à frente, isso resulta em voltar ao local em que o servidor os viu pela última vez. Com todas as correções que eu tentei, isso ainda é perceptível quando você para, porque o servidor para atrás de você
fonte
Na verdade, não implementei isso (pode haver alguns problemas que não estou vendo imediatamente), mas achei que tentaria ajudar.
Aqui está o que você disse que está acontecendo:
Provavelmente seria útil pensar em termos de tempo do servidor. É (provavelmente) muito parecido com o funcionamento da interpolação .
Todo comando é enviado com um horário do servidor. O tempo do servidor é calculado no início de uma partida consultando o tique do servidor, compensando o tempo de ping. No cliente, você tem sua própria contagem de ticks local e cada comando enviado é convertido em ticks de servidor (é uma operação simples de subtração)
Além disso, o cliente está sempre processando "no passado". Portanto, você assume que o mundo que o cliente vê está, digamos, 100ms atrás do que realmente é o tempo do servidor.
Então, vamos reformular seu exemplo com o horário do servidor (designado por S).
O cliente envia entrada em T0 com o tempo do servidor S0 (o que eu acho é realmente "representação do cliente do tempo do servidor menos o tempo de interpolação"). O cliente não espera pela resposta do servidor e move-se imediatamente.
O servidor recebe entrada em T1. O servidor descobre a posição autoritativa do cliente no horário do servidor S0 fornecido pelo cliente. Envia isso para o cliente.
O cliente recebe a posição autoritativa em T2 (ainda com a designação do horário do servidor S0). O cliente controla algum tempo passado de eventos anteriores (provavelmente apenas uma fila de todas as previsões não confirmadas).
Se a posição / velocidade prevista / o que o servidor enviar de volta para S0 for diferente do que o cliente armazenou em S0, o cliente lida com isso de alguma forma. Voltando ao player para a posição anterior, ou re-estimulando a entrada anterior, ou talvez algo que eu não tenha pensado.
fonte
Na verdade, há uma implementação de código aberto no github que mostra como isso é feito. Confira Lance.gg
repositório github: https://github.com/lance-gg/lance
O código de previsão do cliente é implementado no módulo chamado
src/syncStrategies/ExtrapolateStrategy.js
Além da extrapolação, existem dois conceitos que eu não vi mencionados acima:
fonte
O cliente A está sempre à frente do servidor - mas isso não importa. Você só precisa recuperar o cliente se o servidor disser que houve um problema com a posição relatada; nesse momento, o cliente executa novamente todas as alterações feitas desde o erro com os valores corrigidos, para trazê-lo para um estado compatível com o servidor
Para fazer isso, o cliente precisa se lembrar de algumas de suas atualizações e estado anteriores. Pode haver apenas alguns valores simples, como posição, velocidade, orientação, esse tipo de coisa. O servidor enviará periodicamente uma confirmação de que várias atualizações do cliente eram legítimas, o que significa que agora podem ser esquecidas do cliente. Se, no entanto, o servidor relatar que uma atualização é inválida, o estado do cliente reverte para esse ponto e as alterações futuras são aplicadas a esse estado modificado.
Existem alguns links extras na parte inferior do artigo da Valve que valem a pena ler - este é um deles: https://developer.valvesoftware.com/wiki/Prediction
fonte
t=4
) recebe informações sobret=2
, então redefine o estado parat=2
executar novamente as atualizações para trazer objetos det=2
parat=4
?