Pular para o conteúdo principal
O jogo ao vivo

Esta página ainda não foi traduzida: mostrando a versão em inglês.

Visibility

Com 40 jogadores, um snapshot da sala inteira funciona. Com 200, não. Uma zona de visibilidade decide quem recebe o quê, como um predicado declarado, e não como uma chave que você liga objeto por objeto. A difusão e os pacotes por ator são dois modos de entrega declarados do mesmo modelo, então trocar um pelo outro é questão de configuração, e não de reescrever código. É uma otimização do canal, e não uma permissão — para isso, veja Access & Roles.

O mesmo modelo declarado (o predicado, as camadas, os níveis de detalhe) é lido de duas formas:

DifusãoPacotes por ator
Enviaa sala (room) inteira, para todosa cada jogador, só a parte que as regras dele selecionam
Serve parauma sala pequena; é o padrãouma multidão, em que o tamanho do pacote precisa continuar previsível
Lê a declaraçãouma vez, para a salapor ator

O que não pode vazar não está no pacote, em vez de ficar oculto no cliente: nunca é enviado, e por isso é uma propriedade de segurança, e não de banda.

Quando usar

  • Suas salas ficaram grandes demais para a difusão (broadcast) da sala inteira: 200 jogadores precisam de fluxos da vizinhança por cliente, e não de todos os deltas.
  • O estado não pode vazar: névoa de guerra e campos visíveis só para o dono nunca devem ser enviados, em vez de ficarem ocultos no cliente.
  • Várias sessões compartilham um mapa e não podem se ver: uma camada é só mais um predicado.
  • O tamanho do pacote precisa ser previsível numa multidão: limite os objetos e declare a ordem, para que “os N mais próximos” seja uma promessa, e não um acaso da densidade.
  • Um jogador na fronteira precisa enxergar o outro lado: declare quais áreas vizinhas são visíveis, porque, por padrão, só a dele é.
  • Dispensável quando a sala é pequena. O modo de entrega (delivery mode) com pacote compartilhado já cobre esse caso.

Quem faz o quê

AtorO que faz nesta página
schema-authordeclara o predicado de visibilidade, o limite de objetos e sua ordem, quais áreas vizinhas são visíveis e o modo de entrega
anyassina e recebe o que a zona admite; pode baixar o limite de objetos para si mesmo, dentro dos limites declarados

Resumo

Regras de raio e de camada declaradas em Tank; Ammo com escopo do dono, ao lado do campo
[Entity("tank")]
[Visible(Radius = 60)]                           // spatial
[Visible(Rule.SameLayer)]                        // layers of one map
public class Tank
{
    [Sync] public Vector3 Position;
    [Sync(To = Scope.Owner)] public int Ammo;    // per-field scope
}
@Entity('tank')
@Visible({ radius: 60 })                       // spatial
@Visible(Rule.SameLayer)                       // layers of one map
export class Tank {
  @Sync() position!: Vector3;
  @Sync({ to: Scope.Owner }) ammo = 0;         // per-field scope
}
@entity("tank")
@visible(radius=60)                              # spatial
@visible(Rule.SAME_LAYER)                        # layers of one map
class Tank:
    position: Vector3 = sync()
    ammo: int = sync(to=Scope.OWNER)             # per-field scope
Em breve — Go

Ainda não está decidido como declarar com atributos em Go (O-1). Os exemplos chegam quando a forma de escrita for escolhida.

// multi-entry values are one quoted list (a specifier value is a single token)
UCLASS(PSEntity = "tank",
       PSVisible = "radius:60, rule:SameMapInstance")   // spatial + instances of one map
class UTank : public UObject
{
    GENERATED_BODY()

    UPROPERTY(PSSync)                  FVector3f Position;
    UPROPERTY(PSSync = (To = "Owner")) int32     Ammo;   // per-field scope
};
// declarations compile into the same pushed model — playserv push from the UE project or CI
Unity C# is the same C# API here — os mesmos atributos compilam na Unity, na base 2021.3 — sem sintaxe do C# 12 aqui
[Entity("tank")]
[Visible(Radius = 60)]                           // spatial
[Visible(Rule.SameLayer)]                        // layers of one map
public class Tank
{
    [Sync] public Vector3 Position;
    [Sync(To = Scope.Owner)] public int Ammo;    // per-field scope
}

O modelo

O que uma regra de visibilidade declara.

DeclaraO que é
predicadoa própria regra, escrita na mesma linguagem de predicados dos predicados de acesso e das condições de transição. Raio, instância de mapa, equipe e dono são casos particulares de um predicado, e não mecanismos à parte — o contrato tem exatamente uma linguagem desse tipo
limite de objetos e sua ordemuma regra pode limitar o número de objetos, e aí a ordem de seleção é declarada, e não deduzida: “os N mais próximos” é um predicado, mais uma ordenação por distância, mais um limite. Um predicado sozinho não consegue expressar isso, porque responde “esta linha se qualifica?”, e não “qual das qualificadas está mais perto?”
áreas vizinhasse os objetos de uma sala ou instância de mapa vizinha são visíveis, e quais exatamente. Nunca implícito: sem declaração, a área é aquela em que o destinatário está
modo de entregapacote compartilhado: o mesmo conteúdo para todos, barato em CPU. pacote por ator: cada destinatário recebe o seu, conforme a zona dele; caro em CPU e indispensável com populações grandes

O que vale para toda zona.

SempreO que é
visibilidadenão é uma permissão: o que a zona esconde pode estar disponível por permissão, e vice-versa (veja abaixo)
o destinatáriopode baixar o limite: dentro do máximo declarado e nunca abaixo do mínimo declarado, porque o predicado é o mesmo para todos cujo contexto coincidiu, enquanto o tamanho do pacote é problema do destinatário
truncamentoé observável: o destinatário fica sabendo que o pacote foi cortado e por qual ordem. O truncamento silencioso é proibido, porque não dá para distingui-lo da falta de outros objetos
degradaçãoé declarada: quando acaba o orçamento para montar pacotes por ator, a plataforma volta ao pacote compartilhado como foi declarado, em vez de começar a perder destinatários de forma arbitrária
formato do pacoteé uma promessa fraca: o tamanho e a composição de um pacote não deveriam permitir deduzir que existem objetos ocultos

Visibilidade não é permissão

A zona é uma otimização do canal, e não controle de acesso. Não misture os dois: uma configuração de névoa de guerra ampliaria direitos sem ninguém perceber, ou os direitos passariam a depender da distância. O tamanho do pacote pode dar pistas de que existem objetos ocultos; então, quando a existência deles não pode vazar, use as permissões de Access & Roles, e não a zona.

Tanto “quem vê isto?” quanto “o que essa pessoa vê?” podem ser consultados. O custo dos pacotes por ator é uma leitura de primeira classe, no código e no painel.

Erros

  • Um alvo de assinatura (subscription) não declarado é uma recusa de validação.
  • Sem permissão para assinar, a resposta é forbidden ou not found, conforme a existência do alvo seja ou não um segredo: a própria recusa não pode revelar o que está recusando.
  • Uma posição de retomada que não pode ser interpretada é uma requisição inválida, e não um reinício silencioso a partir de agora.
  • Uma assinatura que a plataforma encerrou e um número de assinaturas esgotado são, ambos, conflitos.
  • Ampliar uma visão é fn. Conceder uma visão ampliada e definir níveis de detalhe (detail tier) são recusados com forbidden para uma sessão de jogador, e a visão dela não muda: um cliente espectador não consegue ampliar as próprias permissões concedidas.
  • Uma instância que a visão de quem chama exclui responde not found, a mesma resposta de uma instância inexistente — um forbidden confirmaria que existe algo atrás do muro.
  • Ler o custo dos pacotes por ator é fn adm: uma cloud function ou o painel, nunca um cliente.

Limites

Os números chegam com o capítulo de limites da plataforma; o que acontece em cada teto já está definido.

  • Custo de um pacote por ator: quando o orçamento acaba, a degradação declarada para o pacote compartilhado, com aviso, e nunca a perda arbitrária de destinatários.
  • Objetos por regra: limitados, com uma ordem declarada e uma flag de truncamento observável.
  • Assinaturas por ator: uma nova é recusada, e as existentes continuam.
  • Tamanho do delta: o delta é dividido, e não truncado, e a divisão é observável.
  • Taxa de envio: um limite superior, e não uma garantia.