Andrew Ortiz / MMORPG Devlog 2: Decisiones técnicas iniciales

Created Fri, 10 Oct 2025 18:02:36 -0300

MMORPG Devlog 2: Decisiones Técnicas Iniciales


Los primeros días me he dedicado principalmente a investigar sobre la arquitectura de red: tecnologías, protocolos, etc.

De hecho, estuve experimentando con soluciones de alto nivel que implican ejecutar Unity en el servidor. La conclusión fue que rechacé por completo la idea de usar estas soluciones de tan alto nivel, no por capricho, sino porque después de investigar y leer sobre el tema me di cuenta de que no eran lo suficientemente flexibles y no me iban a permitir hacer lo que yo quería. Además, no me permitirían optimizar lo suficiente el rendimiento de la red.

Network Layer

Luego experimenté con SignalR y pasé un par de días probando hasta que entendí el concepto básico de la arquitectura de red.

Me gusta mucho la Clean Architecture, así que desde el principio hice esta prueba de concepto directamente en capas:

  • Domain
  • Application
  • Adapters
  • Infrastructure

Esto me permitió que, luego de experimentar con SignalR, pudiera cambiar solo la capa de red a UDP con LiteNetLib, y la comparación fue abismal. Ya me lo imaginaba, o era obvio, pero bueno, hasta no ver no creer.

LiteNetLib

Es una librería de C# que permite crear un servidor UDP, pero tiene soporte para paquetes reliable, ordenados y fragmentados. Además, también ofrece una solución de serialización bastante óptima. Nada lujoso, pero súper útil para mi caso.

Login

Para el login decidí crearme un pequeño http service de autenticación, también en C#. Su única responsabilidad es crear cuentas y autenticar usuarios.

Una vez que el usuario se autentica, se crea un token que se envía al cliente (proyecto en Unity). No creo necesitar explicar más acá porque es un simple proceso de autenticación con password hasheado, que en un futuro puede ser cambiado por otro tipo de autenticación. (Google, QR Code, etc.)

Lo importante aquí es que se encarga de crear el token firmado y enviarlo al cliente, solo para usarse entre cliente y servidor.

Una vez que el cliente recibe el token, se lo envía al servidor para que se verifique. Si el token es válido, le asigna una conexión al cliente y ¡magia! :P Ya está logueado client-server

Base de Datos

Con un sistema de autenticación funcionando, el siguiente paso es crear una base de datos que tenga la información de la cuenta del usuario y una por separado para información del mundo, juego, etc.

Al no estar familiarizado con el ecosistema de C#, investigué un poco sobre bases de datos, ORMs, librerías y alguna configuración productiva. Terminé decidiéndome por usar como ORM a Dapper y un sistema simple de migraciones con DbUp donde tengo completo control de los scripts de migración (.sql).

Cache

Esto es súper necesario para el gameplay de un MMO, ya que la latencia es súper importante y no podemos estar consultando la base de datos cada vez que un jugador se mueve o hace alguna acción. Por lo que decidí usar Redis como cache en memoria. Esto me permite tener una latencia súper baja y, además, me permite escalar el sistema de cache si es necesario.

Básicamente, acá lo que hago es: cuando el usuario se loguea y pide información de sus personajes, la primera vez traigo de Postgres la información. Una vez que elige el personaje con el que se va a conectar, guardo en Redis la información de la base de datos. De esta manera, el Repository de personaje solo tiene que consultar Redis y no la base de datos.

Background Service

Por otro lado, el siguiente paso es crear un background service que se encargue de actualizar la información de los personajes en Redis cada cierto tiempo. Por ahora le puse cada 30 segundos. ¡Funciona bastante bien!

Para esto aproveche y uso Microsoft Hosting

Obviamente, a futuro esto se puede mejorar mucho más, pero por ahora es suficiente.


Con esto estoy listo para empezar a trabajar en las pantallas de login, selección de personaje, creación de personaje y conexión al mundo.

Diagrama de Secuencia: Flujo de Autenticación y Conexión

--- config: theme: neo-dark --- sequenceDiagram participant C as Unity Client participant A as Auth Service participant G as Game Server participant R as Redis Cache participant D as PostgreSQL Note over C,D: Fase de Autenticación C->>A: POST /login (username, password) A->>D: Query user credentials D-->>A: User data A->>A: Validate & hash password A->>A: Generate JWT token A-->>C: Return JWT token Note over C,D: Fase de Conexión al Game Server C->>G: UDP Connect + JWT token G->>A: Validate token A-->>G: Token valid ✓ G->>G: Create player session Note over C,D: Fase de Carga de Personajes C->>G: Request character list G->>D: SELECT * FROM characters D-->>G: Character data G->>R: CACHE character data G-->>C: Return character list Note over C,D: Fase de Gameplay C->>G: Select character G->>R: GET character data R-->>G: Cached character G-->>C: Character loaded ✓ Note over C,D: Background Sync loop Every 30 seconds G->>R: GET dirty character data G->>D: UPDATE characters end

Devlog 3: primeras pantallas del juego.