Pular para o conteúdo principal

Hospedagem de Game Server

Última atualização: 15 de setembro de 2026

Um game server é um programa que você escreve e que mantém uma ou mais salas ativas — uma instância autoritativa do seu jogo onde os players realmente jogam. O SDK de servidor oferece a classe base Room para a sua lógica e um RoomHost que executa suas salas, registra-as no PlayServ, mantém-nas vivas com um heartbeat e as aposenta quando terminam. Levar um jogador até uma sala é papel do cliente (Matchmaking e Salas, Conectando-se a um Jogo); esta página é sobre o servidor que é dono da sala.

SDK de servidor, não o cliente do jogo

Este é o SDK do lado do servidor (PlayServ.Sdk.Rooms), usado por um programa que você implanta como game server — não pelo cliente do jogo. Ele se autentica como servidor, então não está sujeito às permissões de tabela voltadas ao cliente. Um game server pode ser uma instância gerenciada que a plataforma lança para você, ou um processo externo que você mesmo roda; ambos usam o mesmo SDK.


A forma de um game server​

Dois tipos fazem o trabalho: uma subclasse de Room guarda o seu jogo, e um RoomHost executa salas desse tipo.

RoomHostexecuta suas salasRoomsua lógicaRegistroassentos · heartbeatClientenavega · entra

Uma sala mínima​

Você cria uma subclasse de Room<TPlayer, TConfig> com seus próprios tipos de jogador e de configuração. A classe base gerencia o roster (AddPlayer, RemovePlayer, Players) e expõe hooks de ciclo de vida que você sobrescreve.

using PlayServ.Sdk.Rooms;

public sealed class MyPlayer : RoomPlayer { }
public sealed record MyConfig;

public sealed class MyRoom : Room<MyPlayer, MyConfig>
{
protected override void OnPlayerJoined(MyPlayer p) { /* dar um assento */ }
protected override void OnPlayerLeft(MyPlayer p) { /* liberar o assento */ }
protected override void OnTick(float dt) { /* avançar a sala */ }
}

Um RoomHost executa salas desse tipo a partir de uma fábrica:

var host = new RoomHost<MyRoom, MyPlayer, MyConfig>(name => new MyRoom());
var room = host.GetOrCreate("lobby-1");

Isso já é um servidor autoritativo funcional: o host conecta o heartbeat, registra a sala, aplica a configuração que puxa da plataforma e cuida do tempo de vida da sala.


Autorregistro e heartbeat​

Você não informa suas salas à plataforma com uma chamada separada — o host registra cada sala automaticamente e a mantém atualizada com um heartbeat periódico que reporta ocupação e capacidade. Esse é exatamente o sinal que o navegador de salas do cliente lê, então uma sala fica descobrível assim que entra em execução e some da navegação pouco depois que o servidor para de enviar heartbeat por ela.


A configuração de sala é da plataforma​

As configurações de sala — capacidade, tempo de vida da reserva, tempo de vida da sala, timeout de inatividade e a cota max_rooms por servidor — são de propriedade da plataforma e editadas no Backoffice, não embarcadas no seu código nem em um manifesto. O host puxa a configuração ao vivo e a aplica conforme muda, então um operador pode retunar um tipo de sala sem um redeploy.

// capacidade e limites vêm da plataforma, não do construtor —
// leia-os da sala em vez de assumir um valor definido no código
observação

Como a config é puxada, mudar a capacidade ou um timeout no Backoffice passa a valer no servidor em execução dentro de um heartbeat. Não fixe esses valores no código; trate o que a plataforma entrega como a fonte da verdade.


Reportar onde a sala está​

Um cliente precisa saber como alcançar a sala. Seu servidor declara seus dados de conexão — host, porta, transporte e, opcionalmente, um connect string e uma região — com DeclareConnect, e a plataforma os devolve ao cliente na sua reserva.

DeclareConnect(new RoomConnect { Host = publicHost, Port = port, Transport = "udp" }, region: "eu");

Quando a plataforma lançou o servidor para você (uma instância gerenciada), os dados de conexão podem ser preenchidos a partir do ambiente do orquestrador automaticamente; quando você roda o seu próprio processo, você os declara.


O ciclo de vida da sala​

Uma sala passa por um ciclo de vida pequeno e bem definido. O host conduz a maior parte; você influencia pelos hooks e por algumas declarações.

EstágioO que acontece
AbertaA sala aceita novos jogadores; o navegador pode exibi-la.
OcupadaJogadores entram e saem; OnPlayerJoined / OnPlayerLeft disparam; o heartbeat reporta a contagem viva.
OciosaTodos saíram. OnIdle dispara; você pode pausar a simulação ou deixar a limpeza aposentar a sala.
DrenandoPerto do fim da vida, a sala para de aceitar novos jogadores enquanto os atuais terminam.
FechadaA sala é aposentada. Fechar marca a sala como fechada em vez de excluí-la, e invalida os tickets de reserva que apontam para ela.

Duas limpezas rodam sem qualquer trabalho seu: a limpeza por ociosidade aposenta salas sem ninguém, e a limpeza por tempo de vida impõe a idade máxima da sala. Ambas respeitam a config de propriedade da plataforma acima.

Tolerância de reconexão

Um jogador que cai mantém o assento por uma breve tolerância de reconexão antes de a sala reportá-lo como ausente, para que uma oscilação de rede não custe o lugar dele. Declare-a com DeclareReconnect(...).


Aceitando jogadores​

Um jogador chega ao seu servidor carregando uma reserva que obteve do SDK cliente. O host valida essa reserva antes de o jogador contar como presente: ela precisa ser válida, não gasta e emitida para esta sala. Só então OnPlayerJoined dispara.

  • Uma reserva válida → o jogador é sentado; OnPlayerJoined(player) roda.
  • Uma reserva ausente, expirada, de sala errada ou já gasta → a entrada é recusada.

É por isso que cliente e servidor são duas metades de um sistema: o cliente reserva e conecta, e o host que você escreve resgata a reserva. Você não valida tickets à mão — o host faz isso — mas você decide o que acontece em OnPlayerJoined / OnPlayerLeft: atribuir um spawn, adicioná-lo ao roster que você transmite, iniciar os timers dele.


Onde o servidor roda​

Um game server pode rodar de algumas formas, e a plataforma mostra qual para cada sala:

  • Gerenciado — a plataforma lança a instância do servidor para você por um orquestrador gerenciado (o PlayServ integra-se com o Edgegap). O token do orquestrador é do seu próprio estúdio, mantido por projeto e ambiente.
  • Externo — você roda o servidor você mesmo (sua própria frota ou máquina). Você o declara ao PlayServ com playserv functions declare como um game server, e ele registra suas salas como qualquer outro. Nunca precisa ser implantado como cloud function.
  • Pooled — uma sala servida a partir de um pool pré-provisionado.

De todo modo o modelo de sala é idêntico: registrar, heartbeat, aceitar reservas, reportar presença.


Capacidade e a cota de lançamentos​

Dois limites diferentes se aplicam. Uma sala tem capacidade — os assentos dentro dela, vindos da config da plataforma. Um game server tem uma cota de salas (max_rooms) — quantas salas podem rodar ao mesmo tempo. Ao atingir a cota, a plataforma recusa lançar outra sala antes de qualquer chamada paga ao orquestrador, então um descontrole nunca vira uma conta alta.


Ambiente​

Um servidor gerenciado recebe o que precisa por variáveis de ambiente PLAYSERV_* — a mais importante, PLAYSERV_DEPLOYMENT_TOKEN, que o SDK troca por uma sessão usada para falar com a plataforma. Você não define isso à mão em um lançamento gerenciado; para um servidor externo, você fornece os equivalentes para o SDK autenticar e registrar.


Próximos passos​