El problema que resuelven#
Para que dos jugadores en casas distintas se conecten, el clásico "conéctate a mi IP" no funciona fácilmente: routers, NAT, puertos cerrados, IPs que cambian. Montar un servidor dedicado cuesta dinero. Unity Relay y Unity Lobby (parte de Unity Gaming Services, UGS) resuelven esto con capa gratuita:
- Relay: retransmite el tráfico entre jugadores a través de servidores de Unity, sin abrir puertos ni compartir IP. El "host" sigue siendo un jugador; Relay solo hace de cartero.
- Lobby: gestiona salas: crear, listar, unirse por código, ver quién está dentro, y guardar datos de la partida.
Relay no ejecuta tu juego: solo reenvía mensajes para sortear el problema de conexión. La lógica sigue en el host (un jugador). Es ideal para cooperativo y partidas pequeñas sin infraestructura. Para autoridad total y escala grande, se usan servidores dedicados.
Cómo encaja con Netcode#
El flujo típico con Netcode for GameObjects:
- El host pide a Relay una allocation y obtiene un join code (un código corto tipo "ABC123").
- El host arranca como servidor usando ese Relay.
- Comparte el join code (por un Lobby, por chat, como quieras).
- Los clientes usan el join code para conectarse a través de Relay.
Inicializar los servicios#
Necesitas el paquete de UGS y autenticación (anónima vale para empezar):
using Unity.Services.Core;
using Unity.Services.Authentication;
using System.Threading.Tasks;
public async Task IniciarServicios()
{
await UnityServices.InitializeAsync();
if (!AuthenticationService.Instance.IsSignedIn)
await AuthenticationService.Instance.SignInAnonymouslyAsync();
}Crear una partida con Relay (host)#
using Unity.Services.Relay;
using Unity.Services.Relay.Models;
using Unity.Networking.Transport.Relay;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
public async Task<string> CrearPartida(int maxJugadores)
{
// 1) Reservar un relay para 'maxJugadores' (sin contar al host)
Allocation alloc = await RelayService.Instance.CreateAllocationAsync(maxJugadores);
// 2) Obtener el código para compartir
string joinCode = await RelayService.Instance.GetJoinCodeAsync(alloc.AllocationId);
// 3) Configurar el transporte de Netcode con los datos del relay
var transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
transport.SetRelayServerData(AllocationUtils.ToRelayServerData(alloc, "dtls"));
// 4) Arrancar como host
NetworkManager.Singleton.StartHost();
return joinCode; // compártelo
}Unirse con el join code (cliente)#
public async Task Unirse(string joinCode)
{
JoinAllocation alloc = await RelayService.Instance.JoinAllocationAsync(joinCode);
var transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
transport.SetRelayServerData(AllocationUtils.ToRelayServerData(alloc, "dtls"));
NetworkManager.Singleton.StartClient();
}Con solo Relay, alguien tiene que pasar el join code por fuera del juego. Lobby lo automatiza: creas una sala pública (o privada), guardas el join code como dato de la sala, y los demás buscan partidas y se unen desde dentro del juego. Lobby + Relay juntos son el combo estándar: Lobby encuentra la partida, Relay conecta.
Lobby en dos líneas de concepto#
LobbyService.Instance.CreateLobbyAsync(nombre, maxJugadores, opciones)crea la sala (guardas ahí el join code de Relay).LobbyService.Instance.QueryLobbiesAsync(...)lista las salas disponibles.LobbyService.Instance.JoinLobbyByCodeAsync(codigo)/JoinLobbyByIdAsync(...)para entrar.- Heartbeat: las salas hay que "mantenerlas vivas" con un ping periódico o Unity las cierra.
Relay vs Steam vs dedicado#
| Unity Relay + Lobby | Steam | Servidor dedicado | |
|---|---|---|---|
| Abrir puertos | No | No | Según montaje |
| Coste | Capa gratis (UGS) | 100 $ Steam (P2P gratis) | De pago (hosting) |
| Plataforma | Cualquiera | Solo Steam (PC) | Cualquiera |
| Autoridad | Host (un jugador) | Host | Servidor real (justo) |
| Ideal para | Cooperativo multiplataforma | Publicar en Steam | Competitivo/escala |
Errores frecuentes#
- No inicializar UGS ni autenticarse antes de usar Relay/Lobby.
- Olvidar el heartbeat del Lobby y que la sala desaparezca.
- Creer que Relay da autoridad de servidor (solo reenvía; el host manda).
- No gestionar errores de red (códigos caducados, sala llena, sin conexión).
- Mezclar Relay con conexión por IP directa sin querer.
Ponte a prueba#
Resumen#
Relay conecta jugadores por internet sin abrir puertos ni IP (retransmite; el host sigue mandando) y Lobby gestiona salas y emparejamiento. El flujo: inicializar UGS → autenticar → host crea allocation y obtiene join code → configura el transporte → StartHost; el cliente hace JoinAllocationAsync(joinCode) → StartClient. Junta Lobby + Relay para que los jugadores se encuentren sin pasar el código a mano. Es la vía moderna de Netcode para publicar sin servidores; compárala con Steam.