Orientación para crear un ranking masivo online en tiempo real

murdokiler

Buenas,

tengo un mente un proyecto, en el que me surgen algunas dudas para la parte online.

Resumiendo el juego, son partidas rápidas de unos 2 minutos de duración, en un juego arcade de un jugador, donde todo el mundo empieza al mismo tiempo la partida y la idea es que la parte online sean las puntuaciones en tiempo real donde en una parte de la pantalla se mostrara un top10 y la posición actual del jugador.

He pensado formas, pero creo que todavía no he encontrado la mejor forma de hacerlo. Una de ellas sería a lo bruto, o mantengo las posiciones actualizadas en el servidor y cada vez que alguien consigue una nueva posición la inserto y ordeno de nuevo, con lo que estaría continuamente trabajando el servidor, y dependiendo el número de jugadores puede ser muy costoso (pienso así de primeras, con bastantes años de experiencia en desarrollo pero muy poquito en online).

Otra forma es que sea el jugador el que ordena esas listas, aunque aquí el problema es en la cantidad de datos innecesarios que tiene que estar recibiendo continuamente. Sí, puedo tener un evento que realice una llamada cada vez que se actualice la lista de puntuaciones, pero el jugador deberá recibir todo el ranking y el ordenarlo, cuando en verdad solo va a necesitar los 10 o 20 primeros puestos y su posición.

En los dos métodos, está claro que solo se actualiza la tabla de puntuaciones cuando la puntuación del jugador es superior a su record anterior.

Tengo experiencia en Firebase nosql y he realizado pruebas con él, también he probado con sql, pero en realidad no sé bien como orientarlo correctamente para no sufrir problemas en un futuro y si la cosa funciona que tenga una buena escala desde un principio.

Otra de las dudas que tengo, es al ser la parte online solo las puntuaciones, si me va a ir mejor crear un servidor que se encargue de manejar todo el tema de empezar partidas y terminar todos a la vez, manejar puntuaciones, etc o sería mejor que todo lo gestionarán los usuarios, que siempre haya un master que se encargué de eso y cuando se desconecta otro jugador pase a ser el master.

De ser la mejor opción un servidor que me recomendáis, Node, Python, Unet (trabajo con unity), el mismo firebase con cloud functions? El juego es para móviles, IOS y Android.

Perdón por el tocho, espero haberme explicado bien, quería dejar claras las dudas.

Gracias, y un saludo.

Edit: Nada, se me olvidó poner un post que tengo en favoritos de stackoverflow, donde se habla del tema. Una de las respuestas es de lo mejor que he encontrado sobre el tema.

https://stackoverflow.com/questions/46720997/leaderboard-ranking-with-firebase

kidandcat

Si guardas los datos en una base de datos SQL, coge los resultados ya ordenados con SQL (order by), no hay nada más rápido que eso.

En cuanto al servidor, el lenguaje el que quieras (total, el ordenamiento lo va a hacer la base de datos), y la base de datos montatela tu en un VPS, si te la administran te va a costar un ojo de la cara. En serio, un MariaDB por defecto en una máquina decente te da para 1.000 writes/s, ya ni te digo lecturas.

Y ya para que te hagas una idea, yo he trabajado con un MySQL en AWS (600-700€/mes) con 1.000 writes/s teniendo unos 2m de clientes actualizando cada 5-10min. Por los 600-700€ es lo que te digo que te montes tu la base de datos, o incluso te sigue saliendo más rentable contratar a un sysadmin freelance que te la instale y mantenga si no sabes que contratarla administrada en una nube.

Y aún más, ya que estoy aqui tienes un ejemplo: https://galax.be
El ordenamiento se hace en el lado del cliente. Otra opción aquí sería recibir el dataset completo, y luego ir recibiendo solo los cambios, y hacer la ordenación en el cliente, de esa forma reducirías la cantidad de datos transmitida.

1 respuesta
r2d2rigo

Si lo haces para moviles, dejate de movidas y usa lo que te da la plataforma...

https://developers.google.com/games/services/android/leaderboards
https://developer.apple.com/game-center/

2 respuestas
kesada7

#3 Pero los leadeboards de google services no te dejan hacer lo que el está pidiendo no? En plan tener en tiempo real actualizándose los leadeboards de la partida algo así como el puesto en el que vas en un juego de carreras.

2 respuestas
murdokiler

Gracias a todos por las respuestas.

#3 creo que no sirve, he trabajado con los dos para mantener los típicos ranking de puntuación, pero no es lo que necesito. El ranking se tiene que actualizar continuamente durante la partida, y los usuarios ver ese ranking en continuo movimiento. Las peticiones son un poco lentas en este caso, creo yo vamos.

#4 es exactamente eso, yo he necesitado 10 párrafos para explicar lo que has resumido en una linea. Trackmania, es el ejemplo perfecto, todo el mundo jugando una misma pista, al menos el primero funcionaba así, podías ver los otros coches fantasma pero no interactuar con ellos, cada uno jugaba a marcar el tiempo, y los rankings se iban actualizando en tiempo real. El juego que yo pretendo hacer no es para nada de coches, pero el sistema de ranking es similar.

#2 Gracias por explayarte y contarme tú experiencia. Básicamente uno de los miedos que tengo es el consumo de procesamiento o ancho de banda, o que al estar continuamente escribiendo y leyendo peticiones, tenga problemas. Y llegar a pagar más de lo que puedo ganar, por no empezar bien desde un principio.

Es interesante lo de recibir el dataset completo y luego ir recibiendo los cambios. ¿Como sería? Se me ocurre comparando checksum o por fechas.

Suponiendo 1000 clientes a la vez, un cliente bate su record, actualiza tabla y los 1000 usuarios reciben la tabla actualizada y ordenada. ¿Es una burrada? Esto puede estar pasando varias veces incluso por segundo, ya que las pruebas serán bastante cortas, y podrás intentarlo varias veces durante el tiempo de la prueba, por lo que cada jugador marcará sus tiempos en distinto orden.

Me tengo que preocupar por esto, ¿o un servidor decente puede aguantarlo? Hablo desde la total ignorancia en este tema, y por eso el miedo. No hace falta una velocidad instantánea, porque no es como un juego donde necesito saber la posición exacta del jugador ms a ms, son datos que da igual que lleguen 1 segundo tarde.

¿Qué pasa si el juego crece? Sabiendo el tipo de online que es, que no importa si la info llega 1 o 2 tarde, ¿podré seguir manteniendo a toda la gente en una misma partida al mismo tiempo?

También se me ocurren alguna forma de reducir las llamadas, por ejemplo que se vaya actualizando cada x segundos en vez de que sea cada vez que se actualiza un tiempo. O para que no todos manden la petición al mismo tiempo, poner un random de margen para que no todas las llamadas se realicen en el mismo momento exacto.

A lo mejor le estoy dando demasiadas vueltas, ya que mi miedo es más en la optimización que en como hacer todo, pero es un juego en el que tengo grandes esperanzas de que pueda ser bastante jugado, no es nada muy grande, pero sí que pienso que puede enganchar bastante.

Bueno, que empiezo a disparar y no paro, de nuevo, muchas gracias por la ayuda.

1 respuesta
kidandcat

Depende completamente de la capa de transporte que uses, ¿es un juego nativo? ¿vas a usar sockets tcp? ¿o es un juego web? si es nativo y usas sockets tcp y un buen encoding binario, o si es web, usando websockets no deberías tener problemas con esa cantidad de información, lo malo es si usas HTTP a pelo para bajartela, entonces si vas a tener problemas. En cuanto a lo del retraso y la escalabilidad, te recomiendo que montes tu sistema de scoreboard completamente separado de tu juego, en un servidor aparte, aunque sea pequeño, así si los recursos no son suficientes lo único que te pasará será que tardará más en actualizarse la tabla de puntuación.

En cuanto a las actializaciones diferenciales, no te hace falta nada de checksum, lo suyo sería que usases websockets o algún protocolo que te permita hacer "push" desde el servidor, entonces el servidor cuando alguien escriba en la BD un nuevo dato, al mismo tiempo que lo escribes en la BD, envías un broadcast a todos los clientes. Entonces un cliente se conecta por primera vez, y pide descargar la tabla completa, a partir de ahi, va recibiendo todas las modificaciones que se hacen a la BD (porque el servidor las envía), no se si me explico bien :P

1 respuesta
totespare

#5 el sistema de fantasmas supongo que no lo quieres, no? Por lo que comentas del trackmania y eso, digo.

Yo había pensado en algo como lo que dices de actualizar cada X segundos. Intentaría tener una cola de peticiones, y o bien cuando se cumplan X peticiones de cambio de puntuación, o X segundos, actualizo tablas y devuelvo el ranking al cliente.

#5murdokiler:

Suponiendo 1000 clientes a la vez, un cliente bate su record, actuali za tabla y los 1000 usuarios reciben la tabla actualizada y ordenada. ¿Es una burrada?

no mucho, ten en cuenta que el servidor enviará a petición del cliente (salvo que quieras hacer broadcast a todos los clientes al mismo tiempo). De hecho, podrías tener otra cola para enviar el ranking, igual que para recibir las puntuaciones.

#5murdokiler:

poner un random de margen para que no todas las llamadas se realicen en el mismo momento exacto.

eso no va a ocurrir nunca, ten en cuenta que cada uno abrirá el juego en un momento del espacio-tiempo diferente xD.

#4 sí dejan, tú haces la petición al servidor de rankings de google y cuando te vuelva la info, la actualizas en pantalla. Es asíncrono (vamos, una corutina).

1 respuesta
murdokiler

#6 El juego es nativo, el motor es Unity, y va a ser para IOS y Android, en un principio, y creo que se quedará ahí ya que los controles están pensados para funcionar bien en táctil.

Al final me he decidido por node y sockets.io, ya que en unity puedo manejar los sockets fácilmente con http pro,

Y sí, te has explicado perfectamente, funciona como un callback, te suscribes y se dispara cuando sea necesario. Hay muchas facilidades para realizarlos tanto en firebase como socket.io, así que voy a optar por este camino. Al final voy a optar por un servidor, voy a empezar haciendo pruebas en heroku y ver como aguanta en el desarrollo, si tenéis alguna recomendación en este aspecto.

#7

#7totespare:

el sistema de fantasmas supongo que no lo quieres, no? Por lo que comentas del trackmania y eso, digo.

Que va, no se van a ver los jugadores unos con otros. De todas formas, tengo entendido que el sistema este está patentado o estaba (como curiosidad más que nada xD)

#7totespare:

eso no va a ocurrir nunca, ten en cuenta que cada uno abrirá el juego en un momento del espacio-tiempo diferente xD.

Sí que ocurrirá, si por ejemplo recibo la notificación de que se ha actualizado la tabla, todos los usuarios suscritos (jugando) reciben la notificación al mismo tiempo (quitando el retardo de la línea), y todos querrán actualizar al mismo tiempo, de ahí a eso que decía.

#7totespare:

sí dejan, tú haces la petición al servidor de rankings de google y cuando te vuelva la info, la actualizas en pantalla. Es asíncrono (vamos, una corutina).

El problema de usar gamecenter o google play, es que yo voy a necesitar un ranking cada dos minutos aprox., ese ranking se reinicia, y después puede ser por tiempos o puntos, es decir va cambiando, y necesito estar continuamente jugando con ellos para mostrar estadísticas, etc... También, ahora no sé, pero antes había problemas para borrar o resetear registros en los ranking de gamecenter, tenían un limite de top (creo que era top100), no se actualizaba muchas veces de forma instantánea, etc... Por eso ya lo descarté, creo que me es más práctico montarme yo un sistema que haga todo esto.

Y nada, que muchas gracias otra vez por los consejos y ayuda, me lanzo ya a por esto, ya tengo bastante avanzado todo el tema de documentación y con muchas ganas de empezar ya a montar todo. En cuanto tenga algo para enseñar, iré mostrando los avances por el foro.

1

Usuarios habituales

  • murdokiler
  • totespare
  • kidandcat
  • kesada7
  • r2d2rigo