Parte: 7 — Multijugador y networking · Fuente: Documentación de Godot 4 (Multiplayer debug tools) + herramientas de red (clumsy en Windows, tc/netem en Linux) ⏱️ Duración estimada: 50 min · Nivel: Avanzado
Aprender a probar tu juego en red bajo malas condiciones a propósito: latencia alta, jitter y pérdida de paquetes. En una LAN todo parece perfecto; los bugs aparecen cuando el ping sube a 150 ms y se pierde un 5 % de los paquetes. Usarás la simulación de red integrada del editor de Godot 4 y herramientas del sistema (clumsy en Windows, tc/netem en Linux) para reproducir esos escenarios, observar cómo reacciona tu interpolación y predicción, y medir métricas. Al terminar sabrás provocar y diagnosticar los fallos de red antes que tus jugadores.
Al finalizar, el alumno podrá:
| # | Tema | Por qué importa |
|---|---|---|
| 1 | Por qué probar en malas condiciones | La red real no es tu LAN; los bugs viven en el lag |
| 2 | Latencia, jitter y pérdida | Cada uno rompe cosas distintas del netcode |
| 3 | Simulación de red del editor Godot | Degradar sin salir del motor, rápido de iterar |
| 4 | clumsy (Windows) | Inyecta lag/pérdida a nivel de sistema |
| 5 | tc/netem (Linux) | Control fino del tráfico en servidores/CI |
| 6 | Efecto sobre interpolación | El suavizado depende de recibir a tiempo |
| 7 | Efecto sobre predicción | El cliente adivina; el lag amplifica el error |
| 8 | Métricas y reproducibilidad | Sin números no hay diagnóstico ni regresión |
Godot 4 incluye un replicador y opciones de depuración de red accesibles desde el editor (menú Debug → Network en las versiones que lo exponen) para inyectar latencia y pérdida en el peer local; consulta la guía de multijugador de Godot (https://docs.godotengine.org/en/stable/tutorials/networking/index.html). En Windows, descarga clumsy (https://jagt.github.io/clumsy/), una herramienta gratuita que degrada el tráfico por filtros. En Linux o en tu servidor headless, usa tc/netem (parte de iproute2). Prepara un proyecto simple con dos peers: un jugador local con predicción y un remoto interpolado usando MultiplayerSynchronizer, para tener algo observable que romper.
Vamos a instrumentar métricas, activar la simulación de red y observar cómo el remoto interpolado "salta" cuando degradamos la conexión.
Paso 1 — Medir el RTT desde GDScript. Un ping periódico cliente↔servidor con marca de tiempo.
# medidor_red.gd — en el cliente
extends Node
var _rtt_ms := 0.0
var _t := 0.0
func _process(delta: float) -> void:
if not multiplayer.has_multiplayer_peer() or multiplayer.is_server():
return
_t += delta
if _t >= 0.5:
_t = 0.0
ping.rpc_id(1, Time.get_ticks_msec())
@rpc("any_peer", "call_remote", "reliable")
func ping(t_cliente: int) -> void:
# corre en el servidor: rebota al emisor
var id := multiplayer.get_remote_sender_id()
pong.rpc_id(id, t_cliente)
@rpc("authority", "call_remote", "reliable")
func pong(t_cliente: int) -> void:
_rtt_ms = Time.get_ticks_msec() - t_cliente
print("RTT = %.0f ms" % _rtt_ms)
Paso 2 — Activar la simulación de red del editor. En Debug → Network (o la sección equivalente de tu versión), fija por ejemplo: latencia entrante/saliente 120 ms, jitter 40 ms, pérdida 5 %. Alternativamente, degrada el sistema completo con clumsy o netem (pasos 4 y 5).
Paso 3 — Remoto interpolado observable. Un MultiplayerSynchronizer replica la posición; suavizamos hacia el último valor recibido para ver el efecto del jitter.
# remoto.gd — nodo del jugador remoto (autoridad del servidor)
extends CharacterBody2D
@onready var _sync: MultiplayerSynchronizer = $MultiplayerSynchronizer
var _objetivo: Vector2
func _ready() -> void:
_objetivo = global_position
func _on_synchronizer_synchronized() -> void:
# nueva posición autoritativa recibida
_objetivo = global_position
func _physics_process(delta: float) -> void:
# interpolación simple hacia el último estado; con jitter, verás tirones
global_position = global_position.lerp(_objetivo, clamp(delta * 12.0, 0.0, 1.0))
Paso 4 — clumsy en Windows.
# Con clumsy abierto (GUI), define un filtro que capture tu puerto de juego, p.ej.:
# udp and (outbound or inbound) and udp.DstPort == 9000
# Activa: Lag 120 ms, Drop 5%, y pulsa Start.
# clumsy no es CLI puro; el filtro se escribe en su ventana.
Paso 5 — tc/netem en Linux.
# Añadir 120 ms de latencia con 40 ms de jitter y 5% de pérdida a la interfaz
sudo tc qdisc add dev eth0 root netem delay 120ms 40ms loss 5%
# Ver el estado aplicado
tc qdisc show dev eth0
# Quitar la degradación al terminar
sudo tc qdisc del dev eth0 root
Observable: con la red limpia el remoto se desliza suave; al aplicar 120 ms + 5 % de pérdida, el RTT impreso sube y el remoto interpolado avanza a tirones y "corrige" de golpe cuando llega un paquete rezagado. Ese comportamiento es exactamente el que debes suavizar o predecir.
lerp y describe cómo cambia el compromiso suavidad/latencia.Entrega una demo con dos peers donde el jugador remoto se interpola y el cliente mide su RTT en pantalla o consola, y demuestra el comportamiento en tres perfiles: red limpia, 100 ms de latencia, y 150 ms + 8 % de pérdida (usando la simulación de Godot, clumsy o netem).
Criterio de aceptación: en red limpia el RTT impreso es cercano a 0–5 ms y el remoto se mueve suave; en el perfil degradado el RTT sube por encima de 100 ms y se observan tirones/correcciones en el remoto; el proceso de activar y desactivar la degradación es reproducible y está documentado.
| Síntoma | Causa y arreglo |
|---|---|
| "Todo va perfecto" y no reproduces bugs | Solo probaste en localhost/LAN; degrada con simulación o netem |
| clumsy no afecta al juego | El filtro no captura el puerto/protocolo correctos; ajústalo al UDP de tu juego |
| netem no hace nada | Interfaz equivocada; usa la real (ip a), no lo para tráfico externo |
| El remoto tiembla incluso sin lag | Interpolas sobre el mismo frame que replicas; separa recepción de render |
| RTT sale negativo o absurdo | Comparas relojes de máquinas distintas; mide ida y vuelta en el mismo peer |
¿No basta con probar en internet real? Internet real no es reproducible: no puedes forzar exactamente 150 ms y 8 % de pérdida a demanda. La simulación te da escenarios repetibles para regresión.
¿Latencia o pérdida rompen cosas distintas? Sí. La latencia retrasa correcciones y desincroniza la predicción; la pérdida crea huecos en el estado que la interpolación debe rellenar.
¿La simulación de Godot sustituye a netem? Para iterar rápido en el editor sí; netem/clumsy prueban el stack completo (SO, driver, socket) y sirven en CI y servidores headless.
¿Debo probar el servidor headless también? Sí. Corre el servidor bajo netem para ver cómo se comporta la simulación autoritativa cuando los clientes llegan tarde.
Clase 152 - Backends: Nakama, Steam y servicios gestionados
Continúa con 154 — Seguridad en multijugador: validación y exploits, donde blindarás el servidor contra clientes tramposos.