Cette page n’est pas encore traduite : la version anglaise est affichée.
Visibility
À 40 joueurs, un snapshot de toute la salle suffit. À 200, non. Une zone de visibilité décide qui reçoit quoi, sous la forme d’un prédicat déclaré et non d’un interrupteur à actionner objet par objet. La diffusion et les paquets par acteur sont deux modes de livraison déclarés d’un même modèle : passer de l’un à l’autre est une affaire de configuration, pas de réécriture. C’est une optimisation du canal, pas une permission — pour cela, voyez Access & Roles.
Un même modèle déclaré — le prédicat, les couches, les niveaux de détail (detail tier) — se lit de deux façons :
| Diffusion | Paquets par acteur | |
|---|---|---|
| Envoie | toute la salle (room), à tout le monde | à chaque joueur, uniquement la part que ses règles sélectionnent |
| Convient à | une petite salle ; c’est le mode par défaut | une foule, où la taille des paquets doit rester prévisible |
| Lit la déclaration | une fois, pour la salle | pour chaque acteur |
Ce qui ne doit pas fuiter est absent du paquet, et non masqué côté client : ce n’est jamais envoyé, ce qui en fait une propriété de sécurité et non une question de bande passante.
Quand l’utiliser
- Vos salles deviennent trop grandes pour diffuser toute la salle : 200 joueurs ont besoin de flux de voisinage par client, pas de chaque delta.
- L’état ne doit pas fuiter : le brouillard de guerre et les champs réservés au propriétaire ne doivent jamais être envoyés, plutôt qu’être masqués côté client.
- Plusieurs sessions partagent une même carte (map) et ne doivent pas se voir : une couche n’est qu’un prédicat de plus.
- La taille des paquets doit rester prévisible dans une foule : plafonnez le nombre d’objets et déclarez l’ordre, pour que « les N plus proches » soit une promesse et non un hasard de densité.
- Un joueur placé à une frontière doit voir au-delà : déclarez quelles zones voisines sont visibles, car par défaut seule la sienne l’est.
- Inutile quand la salle est petite : le mode de livraison (delivery mode) par paquet partagé suffit.
Qui fait quoi
| Acteur | Ce qu’il fait sur cette page |
|---|---|
schema-author | déclare le prédicat de visibilité, le plafond d’objets et son ordre, les zones voisines visibles, et le mode de livraison |
any | s’abonne et reçoit ce que la zone laisse passer ; peut abaisser pour lui-même le plafond d’objets, dans les bornes déclarées |
En bref
Tank ; Ammo réservé à son propriétaire, à même le champ[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 scopeLa déclaration par attributs en Go n’est pas encore tranchée (O-1). Les exemples arriveront quand la forme d’écriture sera choisie.
// 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[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
}Le modèle
Ce que déclare une règle de visibilité.
| Déclare | Ce que c’est |
|---|---|
prédicat | la règle elle-même, écrite dans le même langage de prédicats que les prédicats d’accès et les conditions de transition (guard). Un rayon, une instance de carte, une équipe ou la propriété d’un objet sont des cas particuliers de prédicat, pas des mécanismes à part : le contrat ne connaît qu’un seul langage de ce type |
plafond d'objets et son ordre | une règle peut plafonner le nombre d’objets, et l’ordre de sélection est alors déclaré, pas deviné : « les N plus proches », c’est un prédicat, plus un tri par distance, plus un plafond. Un prédicat seul ne peut pas l’exprimer, car il répond à « cette ligne est-elle retenue ? », pas à « laquelle des lignes retenues est la plus proche ? » |
zones voisines | si les objets d’une salle ou d’une instance de carte voisine sont visibles, et lesquels exactement. Jamais implicite : sans déclaration, la zone est celle où se trouve le destinataire |
mode de livraison | paquet partagé : la même chose pour tout le monde, peu coûteux en CPU. paquet par acteur : chaque destinataire reçoit le sien, selon sa zone ; coûteux en CPU, mais indispensable pour les grandes populations |
Ce qui vaut pour toute zone.
| Toujours | Ce que c’est |
|---|---|
la visibilité | n’est pas une permission : ce que la zone masque peut être accessible par permission, et inversement (voir plus bas) |
le destinataire | peut abaisser le plafond, dans la limite du maximum déclaré et jamais sous le minimum déclaré : un prédicat est le même pour tous ceux dont le contexte correspond, alors que la taille d’un paquet est l’affaire du destinataire |
la troncature | est observable : le destinataire apprend que le paquet a été coupé, et selon quel ordre. La troncature silencieuse est interdite, car rien ne la distinguerait de l’absence d’autres objets |
la dégradation | est déclarée : quand le budget d’assemblage des paquets par acteur est épuisé, la plateforme se replie sur le paquet partagé comme déclaré, au lieu de commencer à perdre des destinataires au hasard |
la forme du paquet | est une promesse faible : la taille et la composition d’un paquet ne devraient pas permettre de déduire l’existence d’objets masqués |
La visibilité n’est pas une permission
La zone est une optimisation du canal, pas un contrôle d’accès. Ne confondez pas les deux : un réglage de brouillard de guerre élargirait les droits en silence, ou bien les droits se mettraient à dépendre de la distance. La taille des paquets peut trahir l’existence d’objets masqués ; là où cette existence ne doit pas fuiter, utilisez les permissions du module Access & Roles, pas la zone.
« Qui voit ceci ? » et « que voient-ils ? » peuvent tous deux être interrogés. Le coût des paquets par acteur se lit directement, au même titre que le reste, dans le code comme dans le panneau.
Erreurs
- Une cible d’abonnement (subscription) non déclarée donne lieu à un refus de validation.
- L’absence de permission pour s’abonner répond forbidden ou not found, selon que l’existence de la cible est secrète ou non : le refus lui-même ne doit pas trahir ce qu’il refuse.
- Une position de reprise illisible est une requête invalide, pas un redémarrage silencieux à partir de maintenant.
- Un abonnement fermé par la plateforme et un nombre d’abonnements épuisé sont tous deux des conflits.
- Élargir une vue relève de
fn. Accorder une vue de surcharge et régler les niveaux de détail sont refusés avec forbidden à une session joueur, dont la vue reste inchangée : un client spectateur ne peut pas élargir les droits qui lui ont été accordés (grant). - Une instance que la vue de l’appelant exclut répond
not found, comme une instance qui n’existe pas : un forbidden confirmerait que quelque chose se trouve derrière le mur. - Lire le coût des paquets par acteur relève de
fnadm: une fonction cloud ou le panneau, jamais un client.
Limites
Les chiffres viendront avec le chapitre sur les limites de la plateforme ; ce qui se passe à chaque plafond, lui, est déjà fixé.
- Le coût d’un paquet par acteur : une fois le budget épuisé, dégradation déclarée vers le paquet partagé, avec un avis, jamais de perte arbitraire de destinataires.
- Objets par règle : plafonnés, avec un ordre déclaré et un indicateur de troncature observable.
- Abonnements par acteur : un nouvel abonnement est refusé, et les existants continuent.
- Taille du delta : le delta est découpé plutôt que tronqué, et le découpage est observable.
- Le rythme d’envoi : une borne supérieure, pas une garantie.