Empieza gratis →

Cómo implementar Relay en Unity para jugar multijugador por internet

L
Lautaro Bravo de la Serna
29 de marzo de 202610 min de lectura
Cómo implementar Relay en Unity para jugar multijugador por internet

Lo que vas a lograr

  • Entender qué es Unity Relay y por qué lo necesitás para jugar por internet
  • Configurar tu proyecto en Unity Dashboard en minutos
  • Escribir el código completo del RelayManager (host + client)
  • Conectar dos jugadores por internet con un Join Code
  • Conocer el error más común y cómo evitarlo

Si ya tenés un juego multijugador en Unity con Netcode for GameObjects, probablemente lo estés probando en tu red local. Funciona perfecto entre dos instancias en tu computadora, o entre dos computadoras en la misma red. Pero si le pasás el juego a un amigo que no está en tu casa... no se puede conectar.

El culpable es el NAT: tu router bloquea conexiones entrantes. Unity Relay soluciona esto actuando como intermediario en la nube — ningún jugador necesita abrir puertos.

🌐

¿Qué es Unity Relay?

Unity Relay es un servicio de Unity Gaming Services (UGS) que permite conectar jugadores a través de internet sin necesidad de un servidor dedicado público. Funciona como un puente: los jugadores se conectan a un servidor intermedio de Unity que retransmite los datos entre ellos. Se integra directamente con Netcode for GameObjects a través del Unity Transport package.

El flujo es simple: el Host crea una partida, recibe un código, lo comparte, y el Client lo usa para conectarse. Todo tu código de gameplay (RPCs, NetworkVariables, NetworkTransform) sigue funcionando sin cambios.

Sin Relay:   Jugador A ──X── Jugador B   (bloqueado)

Con Relay:   Jugador A ──► Relay ◄── Jugador B   (funciona)

Al final de este artículo vas a tener dos jugadores conectados por internet usando Relay. Vamos a cubrir la configuración del proyecto, la instalación de paquetes y el código completo necesario para que funcione.


📋

Requisitos

  • Un proyecto de Unity 2022+ con Netcode for GameObjects funcionando en red local
  • Una cuenta en Unity Dashboard (es gratuita)
Si todavía no tenés un juego multijugador funcionando en local, primero necesitás configurar Netcode for GameObjects. En el curso gratuito de Multiplayer cubrimos todo eso paso a paso.

1

Activar servicios en Unity Dashboard

Antes de escribir código, necesitás vincular tu proyecto con Unity Gaming Services y activar los servicios de Authentication y Relay.

  1. 1En cloud.unity.com, creá o seleccioná tu proyecto
  2. 2Activá los servicios de Authentication y Relay
  3. 3En Unity: Edit > Project Settings > Services → vinculá el proyecto con tu cuenta
Authentication es necesario porque Relay necesita identificar a cada jugador con un ID único. El sign-in anónimo es suficiente — no hace falta que los jugadores creen una cuenta.
2

Instalar paquetes

Abrí el Package Manager (Window > Package Manager), seleccioná Unity Registry e instalá estos dos paquetes:

  • com.unity.services.authentication
  • com.unity.services.relay

Unity Transport (com.unity.transport) ya debería estar instalado si tenés NGO configurado. Verificá que esté actualizado a la última versión.

3

El código del RelayManager

Creá un script RelayManager.cs y agregalo a un GameObject en tu escena. Este script maneja toda la lógica de conexión con Relay:

RelayManager.cs
using System.Linq;
using System.Threading.Tasks;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using Unity.Networking.Transport.Relay;
using Unity.Services.Authentication;
using Unity.Services.Core;
using Unity.Services.Relay;
using UnityEngine;

public class RelayManager : MonoBehaviour
{
    public static RelayManager Instance { get; private set; }
    public string JoinCode { get; private set; }

    void Awake()
    {
        if (Instance != null) { Destroy(gameObject); return; }
        Instance = this;
    }

    public async Task InitializeAsync()
    {
        await UnityServices.InitializeAsync();
        if (!AuthenticationService.Instance.IsSignedIn)
            await AuthenticationService.Instance.SignInAnonymouslyAsync();
    }

    public async Task<string> StartHostWithRelay(int maxPlayers = 4)
    {
        // Reservar espacio en Relay (maxPlayers - 1 porque el Host ocupa un slot)
        var allocation = await RelayService.Instance.CreateAllocationAsync(maxPlayers - 1);
        JoinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);

        // Configurar transporte
        var endpoint = allocation.ServerEndpoints.First(e => e.ConnectionType == "dtls");
        var serverData = new RelayServerData(
            endpoint.Host, (ushort)endpoint.Port,
            allocation.AllocationIdBytes, allocation.ConnectionData,
            allocation.ConnectionData, allocation.Key, true);

        NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(serverData);
        NetworkManager.Singleton.StartHost();
        return JoinCode;
    }

    public async Task StartClientWithRelay(string joinCode)
    {
        var joinAllocation = await RelayService.Instance.JoinAllocationAsync(joinCode);

        // IMPORTANTE: el 5to parametro es HostConnectionData, no ConnectionData
        var endpoint = joinAllocation.ServerEndpoints.First(e => e.ConnectionType == "dtls");
        var serverData = new RelayServerData(
            endpoint.Host, (ushort)endpoint.Port,
            joinAllocation.AllocationIdBytes, joinAllocation.ConnectionData,
            joinAllocation.HostConnectionData, joinAllocation.Key, true);

        NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(serverData);
        NetworkManager.Singleton.StartClient();
    }
}

¿Qué hace cada parte?

  • InitializeAsync: Inicializa Unity Services y hace sign-in anónimo. Llamalo una vez al inicio.
  • StartHostWithRelay: Reserva una asignación en los servidores de Relay, obtiene un Join Code, configura el transporte y arranca como Host.
  • StartClientWithRelay: Usa el Join Code para unirse a la asignación del Host, configura el transporte y arranca como Client.
4

Conectarlo a tu UI

Donde antes llamabas StartHost() y StartClient() directamente, ahora usás el RelayManager:

C#
async void Start()
{
    await RelayManager.Instance.InitializeAsync();
}

// Boton crear partida
async void OnHost()
{
    var code = await RelayManager.Instance.StartHostWithRelay();
    // Mostrar 'code' en pantalla para que lo comparta
}

// Boton unirse
async void OnJoin()
{
    var code = codeInput.text.Trim().ToUpper();
    await RelayManager.Instance.StartClientWithRelay(code);
}

Necesitás un InputField para que el Client escriba el código y un Text para que el Host vea el código generado.

Nota sobre el inspector: en el componente UnityTransport del NetworkManager vas a ver un campo Protocol Type con dos opciones: Unity Transport y Relay Unity Transport. El método SetRelayServerData() lo cambia automáticamente a Relay Unity Transport, pero podés verificarlo desde el inspector.
5

Probar la conexión

  1. 1Hacé un build del proyecto
  2. 2Abrí dos instancias del juego
  3. 3Instancia 1 crea partida → ve el código (ej: A1B2C3)
  4. 4Instancia 2 escribe el código → conecta
  5. 5Tu gameplay funciona igual que en local
Si ambas instancias están en la misma computadora, la conexión sigue pasando por los servidores de Relay. Es una prueba válida de que todo funciona — después podés probarlo con alguien en otra red para confirmar.

⚠️

El error más común

Al construir el RelayServerData, el quinto parámetro es diferente según el rol:

C#
// Host: usa ConnectionData en ambos
... allocation.ConnectionData, allocation.ConnectionData ...

// Client: usa HostConnectionData en el 5to parametro
... joinAllocation.ConnectionData, joinAllocation.HostConnectionData ...
🔴

Si el Client no conecta

Revisá que estés usando HostConnectionData (no ConnectionData) como quinto parámetro del lado del Client. Es el error más común y el más difícil de diagnosticar porque no lanza una excepción — simplemente no conecta.

🔧

Detalles técnicos

Sobre "dtls"

DTLS es UDP con encriptación. Es lo que deberías usar siempre en producción. Las alternativas:

ProtocoloUsoDescripción
"dtls"ProducciónUDP encriptado — la opción por defecto y recomendada
"udp"Solo testingSin encriptación — más rápido pero inseguro
"wss"WebGLObligatorio para builds web — WebSocket seguro

Límites del plan gratuito

💰

50 usuarios concurrentes

El plan gratuito de Relay permite hasta 50 usuarios concurrentes en todas las regiones. Es más que suficiente para desarrollo, testing y juegos pequeños. Si necesitás más, Unity ofrece planes de pago escalables.


🚀

¿Y ahora qué?

Con Relay ya podés jugar con alguien fuera de tu red. Tu proyecto dio un salto grande: pasó de ser algo que solo funciona en tu casa a algo jugable por internet.

Pero si sos honesto, todavía le faltan cosas para ser un juego completo: no tiene lobbies para que los jugadores se encuentren, no tiene un sistema de partidas con score, no tiene personalización, y no maneja bien los errores ni los edge cases del networking.

En el curso completo de Multiplayer en Unity construimos todo eso en 41 lecciones, partiendo desde la misma base que tenés ahora:

Módulo 3: Vida y respawn

Vida, eliminación y respawn sincronizado entre todos los jugadores.

Módulo 4: Flujo de partida

Ready, countdown, score, ganador y personalización de jugador.

Módulo 5: Relay, Lobbies y testing

Relay en profundidad, Lobbies, manejo de errores y herramientas de testing.

Módulo 6: Optimización avanzada

Latencia y compensación, object pooling, sincronización de animaciones, dedicated servers.

Ver el curso completo con 15% de descuento

Como llegaste desde este artículo, te dejo un 15% de descuento pre-aplicado. Los dos primeros módulos son gratis, podés empezar sin pagar y ver si es para vos.

Quiero el curso con el descuento

Preguntas Frecuentes

¿Relay es gratis?

Sí, el plan gratuito permite hasta 50 usuarios concurrentes en todas las regiones. Es suficiente para desarrollo y juegos pequeños. Si necesitás más capacidad, Unity ofrece planes de pago escalables.

¿Necesito un servidor dedicado para usar Relay?

No. Relay usa un modelo host-client donde uno de los jugadores actúa como Host. Los datos pasan por los servidores de Unity como intermediario, pero no necesitás mantener ni pagar un servidor propio.

¿Relay funciona con WebGL?

Sí, pero necesitás usar el protocolo "wss" (WebSocket seguro) en vez de "dtls". Es obligatorio para builds web porque los navegadores no soportan UDP directo.

¿Mi código de gameplay necesita cambios?

No. RPCs, NetworkVariables, NetworkTransform y todo tu código de Netcode for GameObjects sigue funcionando exactamente igual. Relay solo cambia la capa de transporte — cómo se conectan los jugadores, no cómo se comunican.

¿Qué pasa si pierdo el Join Code?

No se puede recuperar. El Host tiene que crear una nueva asignación con StartHostWithRelay(), lo que genera un código nuevo. En un juego real, normalmente combinás Relay con el Lobby Service para que los jugadores se encuentren sin compartir códigos manualmente.

¿Puedo tener más de 4 jugadores?

Sí. El parámetro maxPlayers en StartHostWithRelay() es configurable. Tené en cuenta que el plan gratuito soporta hasta 50 usuarios concurrentes en total (sumando todas las partidas activas).

Si tenés dudas sobre la implementación, preguntá en el Discord de Codearte.

Más contenido gratuito de Unity y desarrollo de juegos en el canal de YouTube.

Multiplayer en Unity: Juego Completo

15% de descuento pre-aplicado · 2 primeros módulos gratis

Ver curso
Tags:#unity#relay#multiplayer#netcode#gamedev#multijugador
🎮

¿Quieres crear tus propios juegos?

Aprende a programar videojuegos desde cero con nuestros cursos en Unity. Más de 3,000 estudiantes ya empezaron su camino.

Ver cursos gratuitos