Estoy haciendo un juego de física de ritmo rápido que es un hockey de mesa. Con dos mazos y un disco. El juego se ejecuta en iphone / ipad y estoy haciendo la parte multijugador a través de GameCenter.
Así es como funciona el sistema de red. El cliente que protagoniza la coincidencia se establecerá como el servidor y el que acepta la solicitud de coincidencia es el cliente.
El 'servidor' tiene la física en ejecución y la respuesta es inmediata y el cliente también tiene su física en ejecución para que se vea suave entre el intercambio de mensajes. Lo que hago como servidor es enviarle al cliente mi velocidad de disco y mi posición, y el cliente ajusta su velocidad / posición de disco relacionada con el servidor para mantenerla sincronizada. De lo contrario, la física se desincroniza y la arruina.
Cuando la latencia de la red es buena, por debajo de 100 ms, los resultados son bastante buenos, obtuve un juego jugable sin problemas en el lado del cliente y el comportamiento extraño es mínimo. El problema ocurre cuando el retraso es de alrededor de 150 a 200 ms. En ese caso, sucede que el disco de mi cliente ya golpeó un borde e invirtió la dirección, pero recibe un mensaje de retraso del servidor y retrocede un poco causando una extraña sensación en el comportamiento de la pelota.
He leído algunas cosas al respecto:
Haga clic en Ejemplo de sincronización
Wikipedia sobre sincronización de reloj
Entonces, ¿cómo puedo resolver esto? Por lo que he leído, la mejor opción que tengo es hacer una sincronización de reloj en el servidor / cliente con una marca de tiempo para que cuando reciba mensajes de retraso relacionados con mi reloj, simplemente ignoro y deje que la simulación de clientes haga trabajo. ¿Están de acuerdo con eso? Y dado que estoy enviando datos poco confiables (UDP), puedo recibir mensajes retrasados o mensajes fuera de servicio.
Si ese es el mejor enfoque, ¿cómo implemento la sincronización del reloj? He leído los pasos sobre cómo hacerlo, pero no lo entendí del todo.
Dice que:
- El cliente marca la hora local actual en un paquete de "solicitud de hora" y lo envía al servidor.
- Al recibir el servidor, el servidor marca la hora del servidor y devuelve
- Al recibirlo el cliente, el cliente resta el tiempo actual del tiempo enviado y lo divide por dos para calcular la latencia. Resta la hora actual de la hora del servidor para determinar el delta de tiempo cliente-servidor y agrega la latencia media para obtener el delta de reloj correcto. (Hasta ahora este algothim es muy similar al SNTP)
- El cliente repite los pasos 1 a 3 cinco o más veces, haciendo una pausa de unos segundos cada vez. Se puede permitir otro tráfico en el ínterin, pero se debe minimizar para obtener mejores resultados. Los resultados de los recibos de paquetes se acumulan y ordenan en orden de latencia más baja a más alta. La latencia media se determina seleccionando la muestra de punto medio de esta lista ordenada.
- Todas las muestras por encima de aproximadamente 1 desviación estándar de la mediana se descartan y las muestras restantes se promedian usando una media aritmética.
Siguiendo este ejemplo, tendría esto:
Supongamos que el juego se ha cargado y que el tiempo de mi cliente es 0 ahora, así que le envío al servidor que mi tiempo es 0.
Los mensajes tardan 150 ms en llegar al servidor, pero el reloj del servidor ya se había iniciado y está 1 segundo por delante del cliente. Cuando el servidor recibe el mensaje, la hora será: 1.15 y envía esa hora al cliente, ¿estamos bien? Supongamos que nuestro retraso es constante a 150 ms.
Ahora el cliente recibe el tiempo 1.15 y resta el tiempo actual del tiempo enviado y lo divide por dos para calcular la latencia. Cuál es: 0.3 - 0 = 0.3 / 2 -> 150ms.
Resta la hora actual de la hora del servidor para determinar el delta de tiempo cliente-servidor y agrega la latencia media para obtener el delta de reloj correcto:
Hora del cliente: 0.3 Hora del servidor 1.15
0.3 - 1.15 = .85 + latencia (.15) = 1
¿Cómo se sincroniza eso? ¿Qué me estoy perdiendo?
Es mi primera vez en multijugador y experiencia en red, así que estoy un poco confundido.
Gracias.
Respuestas:
El algoritmo publicado fue correcto, pero en su ejemplo se está olvidando del tiempo que tarda el paquete del servidor en llegar al cliente, por lo tanto:
Ahora, como puede ver, si el cliente cambió su reloj a 1.15, estaría 0.15 detrás del servidor, es por eso que debe ajustar el Ping (también conocido como Tiempo de ida y vuelta [RTT]). Aquí está el cálculo del tiempo delta completo realizado en muchos pasos:
Esto nos da el tiempo delta correcto de 1.00 segundos
fuente