network-programming physics

network programming - Colisión física de la red de juegos



network-programming physics (8)

¿Cómo se simulan dos vehículos controlados por el cliente colisionando (sensiblemente) en una configuración típica de cliente / servidor para un juego en red? Leí esta publicación de blog eminente sobre cómo hacer física de redes distribuidas en general (sin la predicción tradicional del cliente), pero esta pregunta es específicamente sobre cómo manejar las colisiones de objetos de propiedad.

Ejemplo

Supongamos que el cliente A está 20 ms por delante del servidor, el cliente B 300 ms por delante del servidor (contando tanto la latencia como la máxima inestabilidad). Esto significa que cuando los dos vehículos colisionan, ambos clientes verán al otro como 320 ms atrás, en la dirección opuesta a la velocidad del otro vehículo. ¡De cabeza a cabeza en una carretera sueca significa una diferencia de 16 metros / 17,5 yardas!

Qué no intentar

Es virtualmente imposible extrapolar las posiciones, ya que también tengo vehículos muy complejos con juntas y cuerpos en todas partes, que a su vez tienen posiciones lineales y angulares, velocidades y aceleraciones, sin mencionar los estados de la entrada del usuario.


Perdón por responder con "Qué no probar", pero nunca escuché una solución que no implique predecir el resultado en el lado del cliente. Considera un ejemplo simplificado:

El cliente A está inmóvil y observa cómo el vehículo del cliente B se acerca a un precipicio. El vehículo del cliente B es capaz de reducir la velocidad a 0 instantáneamente, y lo hace en el último momento posible antes de pasar por el acantilado.

Si el Cliente A intenta mostrar el estado del Cliente B en tiempo real, el Cliente A no tiene otra opción que predecir que el Cliente B se cayó del acantilado. Esto se ve mucho en los MMORPG diseñados de tal manera que el personaje de un jugador es capaz de detenerse inmediatamente cuando corre a toda velocidad. De lo contrario, el Cliente A solo podría mostrar el estado del Cliente B cuando ingresen las actualizaciones estatales, pero esto no es viable, ya que el Cliente A debe poder interactuar con el Cliente B en tiempo real en su escenario (supongo).

¿Podría tratar de simplificar los modelos de colisión para que la extrapolación sea posible para la predicción en tiempo real? Tal vez haga que sus "articulaciones y cuerpos en todas partes" tengan modelos físicos sin procesador, como algunos cubos o esferas. No estoy muy familiarizado con la forma de mejorar la eficacia de la detección de colisiones, pero supongo que se hace mediante la detección de colisiones de modelos que son menos complejos que los modelos visuales.


Quizás lo mejor que puedes hacer es no mostrar la colisión real en tiempo real, sino dar la ilusión de que las cosas están sucediendo en tiempo real.

Como el cliente está detrás del servidor (retraso) y el servidor debe mostrar el resultado de la colisión, tal vez lo que puede hacer, el lado del cliente, es mostrar un flash o explosión u otro gráfico para distraer al usuario y comprar lo suficiente tiempo en el lado del servidor para calcular el resultado de la colisión. Cuando haya terminado con la predicción, la envía de vuelta al lado del cliente para su presentación.


Ross tiene un buen punto. Puede simplificar el modelo que usa para detectar colisiones al resumirlo en un volumen más simple (es decir, el contorno cuadrado áspero del vehículo). Luego puede hacer predicciones basadas en el volumen simple y los cálculos detallados de los volúmenes exactos mientras tiene al usuario distraído por la "explosión". Puede que no sea perfecto, pero te permite acelerar la detección de colisiones.


Además de predecir en el lado del cliente dónde podría estar el otro usuario y enviar la información de colisión y cómo lo manejó al servidor, lo que la mayoría de los mmo hacen para lidiar con el retraso es que tienen el servidor funcionando "en el pasado" como si fuera . Básicamente almacenan las entradas recientes pero solo reaccionan a lo que sucedió .1seg en el pasado. Esto le permite "mirar hacia el futuro" cuando lo necesite (es decir, cuando está a punto de producirse una colisión en el marco temporal, puede mirar la entrada almacenada para ver qué sucede y decidir si la colisión es real).

Por supuesto, esto agrega una capa adicional de complejidad a su programa, ya que debe considerar qué datos enviar a sus clientes y cómo deben reaccionar. Por ejemplo, podría enviar todo el búfer "futuro" a los clientes y dejarles ver qué posibles colisiones realmente sucederán y cuáles no.


En cuanto a "Qué no probar". Estás asumiendo que necesitas predecir perfectamente, pero nunca vas a encontrar una solución perfecta en un juego con física compleja. Una aproximación es probablemente lo mejor que puede hacer (por ejemplo, la mayoría de los motores de física comercial pueden moldear la escena de la física y devolver el primer punto de colisión).

Por ejemplo, implementé algunas partes críticas de la física de la red para Mercenaries 2 bajo la guía de Glenn (el póster del blog que mencionas). Era imposible impulsar todo el estado físico necesario a través del cable, incluso para un solo cuerpo rígido. La física Havok genera gradualmente puntos de contacto en cada cuadro, por lo que el "colector de contacto" actual es una parte necesaria del estado físico para mantener la simulación determinista. También es demasiada información. En cambio, enviamos la transformación y las velocidades deseadas y usamos fuerzas y pares para empujar suavemente los cuerpos en su lugar. Los errores son inevitables, por lo que necesita un buen esquema de corrección de errores.


Lo que finalmente terminé haciendo fue simplemente omitir la predicción y simplemente hacer esto:

  1. El cliente tiene mucho que decir sobre su propia posición,
  2. El servidor (casi) solo dice algo acerca de la posición del cliente propietario cuando ocurre una colisión de "alta energía" con otro objeto dinámico (es decir, un entorno no estático).
  3. El cliente toma meshoffset=meshpos-physpos cuando recibe una actualización posicional del servidor y luego establece meshpos=physpos+meshoffset cada fotograma y disminuye gradualmente el meshoffset .

Se ve bastante bien la mayor parte del tiempo (en una situación de baja latencia), ni siquiera tengo que frenar mis cuaterniones para obtener transiciones suaves.

Saltarse la predicción probablemente le da a los clientes de latencia alta una experiencia horrible, pero no tengo tiempo para pensar en esto si alguna vez voy a enviar este juego independiente. De vez en cuando, es bueno crear una solución mediocre que funcione lo suficientemente bien pero lo mejor. ;)

Editar: Eventualmente terminé agregando la característica de "propiedad" que Glen Fiedler (el blogger mencionado en la pregunta) implementó para Mercenaries 2: cada cliente obtiene propiedad de objetos (dinámicos) con los que colisionan por un tiempo. Esto era necesario ya que la penetración de otra manera se vuelve profunda en situaciones de alta latencia y alta velocidad. Esa solución funciona tan bien como pensarías cuando veas la presentación de video de GDC, ¡definitivamente la recomiendo!


Pocos pensamientos.

  1. Peer to peer es mejor para lidiar con latencia y altas velocidades.

Entonces, si este es tu propio motor, cambia a peer to peer. A continuación, extrapola el vehículo del otro compañero en función de la entrada de su botón para avanzar al estado actual. Usted la colisión establecida de modo que colisiona contra el otro vehículo como si fuera mundo. Es decir, tú recibes el golpe.

Esto significa que a medida que colisionas contra el otro, rebotas, en la red de los compañeros te rebotan, por lo que parece más o menos correcto. Cuanto menor es la latencia, mejor funciona.

  1. Si quieres ir cliente / servidor, esto será inferior a p2p

Cosas para intentar o) Extrapolar clientes hacia adelante como en p2p para realizar detección de colisión. o) Enviar resultados de colisión a los clientes y extrapolar hacia adelante

Tenga en cuenta que esto NUNCA va a ser tan bueno como p2p. Fundamentalmente alta velocidad y latencia = error, por lo que la eliminación de la latencia es la mejor estrategia. P2P hace eso.


No sé de una solución perfecta, y tengo la sensación de que uno no existe. Incluso si pudiera predecir con precisión la posición futura del vehículo, no podría predecir la forma en que el usuario operará los controles. Entonces, el problema se reduce a minimizar los efectos negativos del desfase cliente / servidor. Con eso en mente, abordaría esto desde la posición del principio de menos asombro (parafraseado de Wikipedia):

En el diseño de la interfaz de usuario, el principio de menos asombro (o sorpresa) establece que, cuando dos elementos de una interfaz entran en conflicto, o son ambiguos, el comportamiento debería ser el que menos sorprenda al usuario humano en el momento en que surge el conflicto.

En su ejemplo, cada usuario ve dos vehículos. La suya y la de otro jugador. El usuario espera que su propio vehículo se comporte exactamente como lo controla, por lo que no podemos jugar con ese aspecto de la simulación. Sin embargo, el usuario no puede saber exactamente cómo el otro usuario está controlando su vehículo, y yo usaría esta ambigüedad para ocultar el retraso del usuario.

Aquí está la idea básica:

  1. El servidor tiene que tomar la decisión sobre una colisión inminente. El algoritmo de detección de colisión no tiene que ser 100% perfecto, solo tiene que estar lo suficientemente cerca para evitar inconsistencias obvias.
  2. Una vez que el servidor ha determinado que dos vehículos colisionarán, envía a cada uno de los dos usuarios un mensaje que indica que una colisión es inminente.
  3. En el cliente A, la posición del vehículo B se ajusta (de forma realista) para garantizar que se produzca la colisión.
  4. En el cliente B, la posición del vehículo A se ajusta (de forma realista) para garantizar que se produzca la colisión.
  5. Después de la colisión, la posición de cada vehículo se puede ajustar, según sea necesario, para que el resultado final esté en consonancia con el resto del juego. Esta parte es exactamente lo que MedicineMan propuso en su respuesta .

De esta forma, cada usuario todavía tiene el control total de su propio vehículo. Cuando ocurre la colisión, no será inesperado. Cada usuario verá que el otro vehículo se mueve hacia ellos y aún tendrá la sensación de una simulación en tiempo real. Lo bueno es que este método reacciona bien en condiciones de baja demora. Si ambos clientes tienen conexiones de baja latencia al servidor, la cantidad de ajuste será pequeña. El resultado final, por supuesto, empeorará a medida que aumente el retraso, pero eso es inevitable. Si alguien está jugando un juego de acción trepidante a través de una conexión con varios segundos de retraso, simplemente no obtendrá la completa experiencia.