¿Cómo compensar los objetos en movimiento con la predicción del lado del cliente?

11

Estoy implementando un servidor de juegos que admite el combate cuerpo a cuerpo similar a Star Control . Entonces tienes barcos volando y disparando, con física súper simple de velocidad / aceleración / amortiguación para impulsar el movimiento.

ingrese la descripción de la imagen aquí

Leí Valve, Gafferon y Gambetta e implementé el algoritmo de Gambetta para la predicción del cliente:

ingrese la descripción de la imagen aquí

La predicción del cliente funciona en el barco del jugador actualizando su posición desde el servidor tal como viene y luego volviendo a aplicar la entrada aún no procesada por el servidor al barco del jugador.

Desafortunadamente, no funciona bien para mi juego. Creo que tiene que ver con el hecho de que el ejemplo de Gambetta no tiene en cuenta los objetos que ya se están moviendo o los comandos que se actualizan paso a paso. (por "paso" quiero decir marco). Entonces, en mi juego, el jugador presiona hacia arriba para acelerar la nave (ya en movimiento), que continúa moviéndose en el cliente, envía el comando al servidor y generalmente recibe la instantánea mundial del servidor en el siguiente paso. Tengo algo más como:

ingrese la descripción de la imagen aquí

El comando del reproductor se ejecuta en el paso 3 del cliente , pero en el servidor solo se ejecuta en el paso 5 del servidor . Para cuando el cliente recibe la instantánea mundial en el paso 6 del cliente , la predicción está muy lejos, especialmente en velocidades más rápidas.

El quid del problema es que el cliente ejecuta el comando en el paso 5 , pero el servidor lo ejecuta en el paso 6 . Pensé en enviar el paso del cliente con el comando y hacer que el servidor retroceda y vuelva a ejecutar el comando con el paso de tiempo del cliente. Sin embargo, eso podría conducir a una serie de otros problemas, como lo que sucede con los comandos recibidos desde la reversión, o cómo los clientes engañadores pueden explotar cambiando el paso enviado.

Leer y mirar videos como este de Google menciona un enfoque diferente, donde cambia gradualmente la posición del jugador para que coincida con la de la instantánea en unos pocos pasos.

Mis preguntas:

  • ¿Puedes hacer que el algoritmo de Gambetta funcione con movimientos constantes? ¿O es conceptualmente incompatible con mi juego?

  • ¿Es la interpolación gradual sobre los pasos el camino correcto a seguir entonces? Si es así, ¿cómo interpola un objeto ya en movimiento desde la posición del cliente para que coincida con el que acaba de recibir del servidor?

  • ¿Pueden estos métodos, la interpolación gradual y el algoritmo de Gambetta funcionar en conjunto, o son mutuamente excluyentes?

OpherV
fuente
He estado haciendo lo mismo y me he encontrado exactamente con el mismo problema. Tan pronto como agregué velocidades aplicando el estado del servidor y volviendo a aplicar las entradas, eliminé los cambios de velocidad ya manejados. He estado intentando volver a aplicar todas las actualizaciones desde el último mensaje recibido, pero aún no es muy sencillo. ¿Alguna vez has encontrado una solución para esto?
MakuraYami
@MakuraYami Sí, comencé a escribir un artículo que describe la solución. Se actualizará pronto!
OpherV
He trabajado más en mi proyecto y encontré una solución utilizable y algunos recursos más buenos sobre este tema. Estoy interesado en discutir más, comparar soluciones, etc. Avíseme dónde puedo comunicarme con usted :)
MakuraYami
@makurayami mi nombre de usuario en Gmail
OpherV

Respuestas:

5

Durante los 6 meses transcurridos desde que hice esta pregunta, terminé desarrollando un servidor de juegos de código abierto completo para tratar este problema exacto (¡y muchos otros!): Http://lance.gg

ingrese la descripción de la imagen aquí

La I + D involucrada ahora me permite responder mis propias preguntas:

  • ¿Puedes hacer que el algoritmo de Gambetta funcione con movimientos constantes? ¿O es conceptualmente incompatible con mi juego?

    El algoritmo de Gambetta no funcionará cuando el movimiento de la entidad no sea determinista (desde el punto de vista del cliente). Si una entidad puede verse afectada sin aportes de la física u otros jugadores, por ejemplo, se debe adoptar un enfoque más similar.

  • ¿Es la interpolación gradual sobre los pasos el camino correcto a seguir entonces? Si es así, ¿cómo interpola un objeto ya en movimiento desde la posición del cliente para que coincida con el que acaba de recibir del servidor?

    Esto toca un tema diferente, que es la conciliación del cliente de las actualizaciones del servidor. La interpolación gradual funciona, pero para juegos de ritmo muy rápido como el de la pregunta, es mejor implementar la extrapolación

  • ¿Pueden estos métodos, la interpolación gradual y el algoritmo de Gambetta funcionar en conjunto, o son mutuamente excluyentes?

    Pueden trabajar juntos, pero solo si el movimiento de la entidad es determinista desde el punto de vista del cliente. Por lo tanto, no funcionará si la entidad se ve afectada por la física o la psuedo-física, como la inserción, el arrastre, etc.

OpherV
fuente
1

Su juego parece ser demasiado "en tiempo real" para pensar en términos de pasos de tiempo. Solo pensaría en términos de "turnos" si el juego puede considerarse "basado en turnos". De lo contrario, simplemente abandone la idea de giros o pasos. Todo se vuelve más fácil entonces :)

Tenga en cuenta que predice localmente para su jugador e interpola solo para otras entidades (como se explica en el tercer artículo de la serie). La forma de lidiar con las actualizaciones del servidor para los objetos que ya se estaban moviendo es la reconciliación del lado del servidor, explicada en la mitad inferior del segundo artículo (al que se vinculó).

Espero que esto ayude :)

ggambett
fuente
Solo para aclarar: por "paso" me refiero a "marco", que se ejecuta 60 veces por segundo. Lo llamo paso (y no marco) para diferenciar la progresión real del juego del renderizado, e idealmente ambos están sincronizados a 60 por segundo. Ya implementé su versión de la reconciliación del lado del servidor que funciona de manera brillante. Esta pregunta solo se refiere a la nave del jugador, que se mueve constantemente independientemente del comando del jugador (debido a la inercia). Ahí es donde radica mi dificultad. ¿Alguna idea sobre eso? :)
OpherV
Los marcos son diferentes a los pasos. Los pasos se mueven en un orden constante y predecible. Los cuadros se mueven una cantidad de tiempo variable, por lo que cualquier progresión debe multiplicarse por el tiempo delta para ese cuadro.
Tealr
@Tealr, de hecho, es por eso que usé el término "paso" para comenzar, solo quería aclarar que el uso de "paso" no se limita a los juegos por turnos, y en mi juego un paso toma exactamente 1 / 60 de segundo, independientemente de la representación.
OpherV
Solo algo que noto para mi propio experimento: 1/60. es inusualmente rápido y apuesto a que la mayoría de los juegos en línea con más de 1x1 de participación funcionan a 1 / 10s. actualizaciones o por ahí.
Patrick Hughes